void cDragItems::dropItem( P_CLIENT client ) { P_CHAR pChar = client->player(); // Get the data SERIAL itemId = LongFromCharPtr( &buffer[ client->socket() ][ 1 ] ); SERIAL contId = LongFromCharPtr( &buffer[ client->socket() ][ 10 ] ); Coord_cl dropPos = pChar->pos; // plane+map dropPos.x = ShortFromCharPtr( &buffer[ client->socket() ][ 5 ] ); dropPos.y = ShortFromCharPtr( &buffer[ client->socket() ][ 7 ] ); dropPos.z = buffer[ client->socket() ][ 9 ]; // Get possible containers P_ITEM pItem = FindItemBySerial( itemId ); if( !pItem ) return; P_ITEM iCont = FindItemBySerial( contId ); P_CHAR cCont = FindCharBySerial( contId ); /* >> SEE LORD BINARIES DROPFIXBUGFIXBUG << */ // A completely invalid Drop packet if( !iCont && !cCont && ( dropPos.x == 0xFFFF ) && ( dropPos.y == 0xFFFF ) && ( dropPos.z == 0xFF ) ) { bounceItem( client, pItem ); return; } // Item dropped on Ground if( !iCont && !cCont ) dropOnGround( client, pItem, dropPos ); // Item dropped on another item else if( iCont ) dropOnItem( client, pItem, iCont, dropPos ); // Item dropped on char else if( cCont ) dropOnChar( client, pItem, cCont ); }
void cFishing::FishTarget(P_CLIENT ps) { // fixes an exploit with fishing, LB int px,py,cx,cy; UOXSOCKET s=ps->GetSocket(); P_CHAR pPlayer=ps->getPlayer(); if (!pPlayer) return; px=((buffer[s][0x0b]<<8)+(buffer[s][0x0c]%256)); py=((buffer[s][0x0d]<<8)+(buffer[s][0x0e]%256)); cx=abs(pPlayer->pos.x-px); cy=abs(pPlayer->pos.y-py); // int cz=abs(pPlayer->z-buffer[s][0x10]); if(!(cx<=6 && cy<=6)) { ps->SysMsg("You are too far away to reach that"); return; } // end exploit fix bool ok=false; if (IsFishWater(ShortFromCharPtr(buffer[s]+0x11))) ok = true; else { // it might be offshore fishing (client returns id=0 for deep sea ) Duke, Thx for the hint goes to Avanoon guys map_st map = Map->SeekMap0(px, py); // search the ground tile where they casted if ( map.id == 0x00A8 || map.id == 0x00A9 || map.id == 0x00AA || map.id == 0x00AB ) ok = true; } if (ok) { action(s,0x0b); if ((buffer[s][1]==1 || buffer[s][1]==0)&&(buffer[s][2]==0)&&(buffer[s][3]==1)&&(buffer[s][4]==0)) { if (fishing_data.randomtime!=0) pPlayer->fishingtimer=rand()%fishing_data.randomtime+fishing_data.basetime; else pPlayer->fishingtimer=fishing_data.basetime; } soundeffect(s, 0x02, 0x3F); pPlayer->unhide(); Fish(DEREF_P_CHAR(pPlayer)); } else ps->SysMsg("You need to be closer to the water to fish!"); }
void cFishing::FishTarget(P_CLIENT ps) { // fixes an exploit with fishing, LB int px,py,cx,cy; UOXSOCKET s=ps->socket(); P_CHAR pPlayer=ps->player(); if (!pPlayer) return; px=((buffer[s][0x0b]<<8)+(buffer[s][0x0c]%256)); py=((buffer[s][0x0d]<<8)+(buffer[s][0x0e]%256)); cx=abs(pPlayer->pos.x-px); cy=abs(pPlayer->pos.y-py); // int cz=abs(pPlayer->z-buffer[s][0x10]); if(!(cx<=6 && cy<=6)) { sysmessage(s, "You are too far away to reach that"); return; } // end exploit fix bool ok=false; if (IsFishWater(ShortFromCharPtr(buffer[s]+0x11))) ok = true; else { // it might be offshore fishing (client returns id=0 for deep sea ) Duke, Thx for the hint goes to Avanoon guys map_st map = Map->SeekMap(Coord_cl(px, py, pPlayer->pos.map)); // search the ground tile where they casted if ( map.id == 0x00A8 || map.id == 0x00A9 || map.id == 0x00AA || map.id == 0x00AB ) ok = true; } if (ok) { action(s,0x0b); if (SrvParams->randomtime()!=0) pPlayer->setFishingtimer(rand()%SrvParams->randomtime()+SrvParams->basetime()); else pPlayer->setFishingtimer(SrvParams->basetime()); soundeffect(s, 0x02, 0x3F); pPlayer->unhide(); Fish(pPlayer); } else sysmessage(s, "You need to be closer to the water to fish!"); }
void cSpeech::talking(int s, QString speech) // PC speech { /* Unicode speech format byte = char, short = char[2], int = char[4], wchar = char[2] = unicode character Message Sent By Client: 0xAD - Unicode Speech Request BYTE cmd(0xAD) short msgsize 1, 2 byte type(0 = say, 2 = emote, 8 = whisper, 9 = yell) 3 short color 4, 5 short font 6, 7 BYTE[4] lang(null terminated, "enu " for US english.) 8, 9, 10, 11 wchar[?] text(null terminated, ?=(msgsize - 12)/2) 13 Message Sent By Server: 0xAE - Unicode Speech Message BYTE cmd(0xAE) 0 short msgsize 1, 2 BYTE[4] ser(ser of speaker, all 0xFF if none) 3, 4, 5, 6 BYTE[2] model(id of speaker, all 0xFF if none)7, 8 BYTE type 9 short color 10, 11 short font 12, 13 BYTE[4] language(same as before) 14, 15, 16, 17 BYTE[30] speaker's name(normal chars, not wchars) 18 - 48 WCHAR[?] text(null terminated, ?=(msgsize - 48)/2 Importnat note regarding 0xAD: since 2.0.7 clients send between lang and text 0...10 bytes. (we can ignore them safely) Those bytes get cut out in network.cpp correctly, so the buffer THIS functions sees is actualy what is written above. The actual data the client sends is differently though. Just noted this to prevent from debugging if somebody finds out client data doesn't fit to this description (LB) */ //char nonuni[512]; unsigned char talk2[19]; QByteArray unicodetext; char lang[4]; char name[50] = {0,}; // it **IS** important to 0 out the remaining gaps P_CHAR pc_currchar = currchar[s]; // strcpy(nonuni, speech.latin1()); // len+font+color+type = same postion for non unicode and unicode speech packets // but 8 ... x DIFFER a lot for unicode and non unicode packets !!! strncpy(name, pc_currchar->name.c_str(), 50); char speech_type = buffer[s][3]; UI16 speech_color = ShortFromCharPtr(&buffer[s][4]); char speech_fontbyte1 = buffer[s][6]; char speech_fontbyte2 = buffer[s][7]; int ucl = ( speech.length() * 2 ) + 2; int tl = ucl + 48 ; if (pc_currchar->unicode) { lang[0]=buffer[s][8]; lang[1]=buffer[s][9]; lang[2]=buffer[s][10]; lang[3]=buffer[s][11]; unicodetext.duplicate( (char*)&buffer[s][12], ucl ); } else { lang[0]='E'; lang[1]='N'; lang[2]='U'; lang[3]=0; char2wchar(speech.latin1()); // we are sending unicode response no matter if the speech request was non unicode or not // so convert to uni-text in case of non unicode unicodetext.duplicate( (char*)&temp, ucl ); } /* clConsole.send("speech: %s\n",nonuni); clConsole.send("unicode speech:\n"); for ( a=0; a < tl-48; a++) clConsole.send("%02i ",unicodetext[a]); clConsole.send("\n");*/ //// Very important: do not use buffer[s][] anymore in this function !!!! //// unicode text that gets send is in unicodetext, nonunicode text for normal string processing in non uni code // string punt(nonuni); if (InputSpeech(speech, pc_currchar, s)) // handle things like renaming or describing an item return; if (pc_currchar->squelched) // not allowed to talk { sysmessage(s, "You have been squelched."); return; } // AntiChrist pc_currchar->unhide(); if (speech[0] == (char)SrvParams->commandPrefix() ) { Commands->Command(s, speech.latin1()); return; } if ( speech_type == '\x09' && pc_currchar->canBroadcast() ) { broadcast(s); return; } talk2[0] = 0xAE; ShortToCharPtr(tl, &talk2[1]); LongToCharPtr(pc_currchar->serial, &talk2[3]); ShortToCharPtr(pc_currchar->id(), &talk2[7]); talk2[9] = speech_type; ShortToCharPtr(speech_color, &talk2[10]); talk2[12] = speech_fontbyte1; talk2[13] = speech_fontbyte2; talk2[14] = lang[0]; talk2[15] = lang[1]; talk2[16] = lang[2]; talk2[17] = lang[3]; Xsend(s, talk2, 18); Xsend(s, name, 30); Xsend(s, unicodetext.data(), unicodetext.size()); if (speech_type == 0 || speech_type == 2) { pc_currchar->saycolor = speech_color; } if (SrvParams->speechLog()) // Logging bugfixed by LB { char temp2[512]; sprintf(temp2, "%s.speech_log", pc_currchar->name.c_str()); sprintf((char*)temp, "%s [%x] [%i] said:\n%s\n", pc_currchar->name.c_str(), pc_currchar->serial, pc_currchar->account, speech.latin1()); savelog((char*)temp, (char*)temp2); } //char SpeechUpr[512]; //strcpy(SpeechUpr, nonuni); //strupr(SpeechUpr); QString SpeechUpr = speech.upper(); //transform(SpeechUpr.begin(), SpeechUpr.end(), SpeechUpr.begin(), ::toupper); //if (!strcmp(SpeechUpr, "I RESIGN FROM MY GUILD")) if (SpeechUpr == "I RESIGN FROM MY GUILD") { GuildResign(s); } if (response(s,pc_currchar, SpeechUpr)) return; // Vendor responded already //if (strstr(SpeechUpr, "GUARDS")) if (SpeechUpr.contains("GUARDS")) callguards(currchar[s]); if (Boats->Speech(s, SpeechUpr)) return; house_speech(s, SpeechUpr); // houses crackerjack 8/12/99 int i, j; for (i = 0; i < now; i++) { // AntiChrist - don't check line of sight for talking!!! if (inrange1(i, s) && perm[i] && i!=s)//&&line_of_sight(s, pc_currchar->pos.x, pc_currchar->pos.y, pc_currchar->pos.z, chars[currchar[i]].x, chars[currchar[i]].y, chars[currchar[i]].z, WALLS_CHIMNEYS + DOORS + FLOORS_FLAT_ROOFING)) { Xsend(i, talk2, 18); Xsend(i, name, 30); if (pc_currchar->dead // a ghost is talking && !currchar[i]->dead // Ghost can talk normally to other ghosts && !currchar[i]->isGMorCounselor()// GM/Counselors can see ghosts talking always Seers? && currchar[i]->spiritspeaktimer == 0) { unsigned char ghostspeech[512]; memcpy(&ghostspeech, unicodetext.data(), unicodetext.size()); for (j = 1; j < ucl-2 ; j += 2) // -2: dont override /0 /0 terminator ! { if (ghostspeech[j] != 32) // keep the blanks ghostspeech[j] = (ghostspeech[j]%2) ? 'O' : 'o'; } Xsend(i, ghostspeech, ucl); // send 'ghostified' speech "OOoooOo Ooo" } else Xsend(i, unicodetext.data(), unicodetext.size()); } } if (pc_currchar->dead) return; // this makes it so npcs do not respond to dead people cChar* pc=NULL; cChar* pNpc=NULL; cRegion::RegionIterator4Chars ri(pc_currchar->pos); for (ri.Begin(); !ri.atEnd(); ri++) { pc = ri.GetData(); if (!pc->isSameAs(pc_currchar) && pc->isNpc() && pc->dist(pc_currchar) <= 2) { pNpc=pc; break; } } if (pNpc && pNpc->speech) { Script *pScp=i_scripts[speech_script]; if (!pScp->Open()) return; char sect[512]; sprintf(sect, "SPEECH %i", pNpc->speech); if (!pScp->find(sect)) { pScp->Close(); return; } int match = 0; strcpy(sect, "NO DEFAULT TEXT DEFINED"); unsigned long loopexit = 0; do { pScp->NextLineSplitted(); if (script1[0] != '}') { if (!(strcmp("DEFAULT", (char*)script1))) { strcpy(sect, (char*)script2); } if (!(strcmp("ON", (char*)script1))) { char scpUpr[500]; strcpy(scpUpr,script2); strupr(scpUpr); if (SpeechUpr.find(scpUpr)!= string::npos) match=1; } if (!(strcmp("SAY", (char*)script1))) { if (match == 1) { npctalk(s, pNpc, (char*)script2, 0); match = 2; } } if (!(strcmp("TRG", (char*)script1))) // Added by Magius(CHE) § { if (match == 1) { pNpc->trigger = str2num(script2); scpMark m=pScp->Suspend(); Trig->triggernpc(s, pNpc, 1); pScp->Resume(m); strcpy((char*)script1, "DUMMY"); match = 2; } } } } while (script1[0] != '}' && (++loopexit < MAXLOOPS)); if (match == 0) { npctalk(s, pNpc, sect, 0); } pScp->Close(); } }
void cTrade::sellaction(int s) { int i, amt, value=0, totgold=0; P_ITEM pRestock = NULL; P_ITEM pNoRestock = NULL; P_ITEM pSellCont = NULL; if (buffer[s][8]!=0) { P_CHAR pc_n = FindCharBySerial(calcserial(buffer[s][3], buffer[s][4], buffer[s][5], buffer[s][6])); if (pc_n == NULL) return; P_ITEM pi; unsigned int ci; vector<SERIAL> vecContainer = contsp.getData(pc_n->serial); for ( ci = 0; ci < vecContainer.size(); ci++) { pi = FindItemBySerial(vecContainer[ci]); if (pi->layer==0x1A) pRestock = pi; // Buy Restock container else if (pi->layer==0x1B) pNoRestock = pi; // Buy no restock container else if (pi->layer==0x1C) pSellCont = pi; // Sell container } // Pre Calculate Total Amount of selling items to STOPS if the items if greater than SELLMAXITEM - Magius(CHE) int maxsell=0; i=buffer[s][8]; if (i>256) return; for (i=0;i<buffer[s][8];i++) { amt=ShortFromCharPtr(buffer[s]+9+(6*i)+4); maxsell+=amt; } if (maxsell>SrvParams->sellmaxitem()) { char tmpmsg[256]; sprintf(tmpmsg,"Sorry %s but i can buy only %i items at time!",currchar[s]->name.c_str(),SrvParams->sellmaxitem()); npctalkall(pc_n, tmpmsg,0); return; } for (i=0;i<buffer[s][8];i++) { P_ITEM pSell=FindItemBySerPtr(buffer[s]+9+(6*i)); // the item to sell if (!pSell) continue; amt=ShortFromCharPtr(buffer[s]+9+(6*i)+4); // player may have taken items out of his bp while the sell menu was up ;-) if (pSell->amount<amt) { npctalkall(pc_n, "Cheating scum! Leave now, before I call the guards!",0); return; } // Search the buy restock Container P_ITEM join = NULL; ci=0; P_ITEM pi; vector<SERIAL> vecContainer = contsp.getData(pRestock->serial); for ( ci = 0; ci < vecContainer.size(); ci++) { pi = FindItemBySerial(vecContainer[ci]); if (items_match(pi,pSell)) join = pi; } // Search the sell Container to determine the price ci=0; vecContainer.clear(); vecContainer = contsp.getData(pSellCont->serial); for ( ci = 0; ci < vecContainer.size(); ci++) { pi = FindItemBySerial(vecContainer[ci]); if (items_match(pi,pSell)) { value=pi->value; value=calcValue(pSell, value); if (SrvParams->trade_system()==1) value=calcGoodValue(currchar[s], pSell, value, 1); // Fixed for adv trade --- by Magius(CHE) § break; // let's take the first match } } totgold+=(amt*value); // add to the bill if (join != NULL) // The item goes to the container with restockable items { join->amount+=amt; join->restock-=amt; pSell->ReduceAmount(amt); } else { pSell->SetContSerial(pNoRestock->serial); SndRemoveitem(pSell->serial); if (pSell->amount!=amt) Commands->DupeItem(s, pSell, pSell->amount-amt); } } addgold(s, totgold); goldsfx(s, totgold); // Dupois, SFX for gold movement // Added Oct 08, 1998 } char clearmsg[9]; clearmsg[0]=0x3B; clearmsg[1]=0x00; clearmsg[2]=0x08; clearmsg[3]=buffer[s][3]; clearmsg[4]=buffer[s][4]; clearmsg[5]=buffer[s][5]; clearmsg[6]=buffer[s][6]; clearmsg[7]=0x00; Xsend(s, clearmsg, 8); }
/*! \author Zippy \brief Build an house Triggered by double clicking a deed-> the deed's morex is read for the house section in house.cpp. Extra items can be added using HOUSE ITEM, (this includes all doors!) and locked "LOCK" Space around the house with SPACEX/Y and CHAR offset CHARX/Y/Z \todo Remove temp variable */ void buildhouse( pClient client, pTarget t ) { int i = t->buffer[2]; char temp[TEMP_STR_SIZE]; //xan -> this overrides the global temp var int loopexit=0;//where they click, and the house/key items uint32_t k, sx = 0, sy = 0, icount=0; uint16_t x, y, id_tile; int16_t z; int hitem[100];//extra "house items" (up to 100) char sect[512]; //file reading char itemsdecay = 0; // set to 1 to make stuff decay in houses static int looptimes=0; //for targeting int cx=0,cy=0,cz=8; //where the char is moved to when they place the house (Inside, on the steps.. etc...)(Offset) int boat=0;//Boats int hdeed=0;//deed id # int norealmulti=0,nokey=0,othername=0; char name[512]; pChar pc = client->currChar(); if ( ! pc ) return; sLocation charpos= pc->getPosition(); int16_t id = INVALID; //house ID hitem[0]=0;//avoid problems if there are no HOUSE_ITEMs by initializing the first one as 0 if (i) { cScpIterator* iter = NULL; char script1[1024]; char script2[1024]; sprintf(sect, "SECTION HOUSE %d", i);//and BTW, .find() adds SECTION on there for you.... iter = Scripts::House->getNewIterator(sect); if (iter==NULL) return; do { iter->parseLine(script1, script2); if ((script1[0]!='}')&&(script1[0]!='{')) { if (!(strcmp(script1,"ID"))) { id = hex2num(script2); } else if (!(strcmp(script1,"SPACEX"))) { sx=str2num(script2)+1; } else if (!(strcmp(script1,"SPACEY"))) { sy=str2num(script2)+1; } else if (!(strcmp(script1,"CHARX"))) { cx=str2num(script2); } else if (!(strcmp(script1,"CHARY"))) { cy=str2num(script2); } else if (!(strcmp(script1,"CHARZ"))) { cz=str2num(script2); } else if( !(strcmp(script1, "ITEMSDECAY" ))) { itemsdecay = str2num( script2 ); } else if (!(strcmp(script1,"HOUSE_ITEM"))) { hitem[icount]=str2num(script2); icount++; } else if (!(strcmp(script1, "HOUSE_DEED"))) { hdeed=str2num(script2); } else if (!(strcmp(script1, "BOAT"))) boat=1;//Boats else if (!(strcmp(script1, "NOREALMULTI"))) norealmulti=1; // LB bugfix for pentas crashing client else if (!(strcmp(script1, "NOKEY"))) nokey=1; else if (!(strcmp(script1, "NAME"))) { strcpy(name,script2); othername=1; } } } while ( (strcmp(script1,"}")) && (++loopexit < MAXLOOPS) ); safedelete(iter); if (!id) { ErrOut("Bad house script # %i!\n",i); return; } } if(!looptimes) { if (i) { if (norealmulti) { pTarget targ = clientInfo[s]->newTarget( new cLocationTarget() ); targ->code_callback=buildhouse; ShortToCharPtr(0x4064, t->buffer); targ->send( ps ); ps->sysmsg( "Select a place for your structure: "); } else client->sysmessage("Select location for building."); nPackets::Sent::TargetMulti pk(0x00010000/*serial*/, id -0x4000/*model*/); client->sendPacket(&pk); } else { client->sysmessage("Select location for building."); nPackets::Sent::TargetMulti pk(0x00010000/*serial*/, ShortFromCharPtr(t->buffer) -0x4000/*model*/); client->sendPacket(&pk); } looptimes++;//for when we come back after they target something return; } if(looptimes) { looptimes=0; if(!pc->IsGM() && SrvParms->houseintown==0) { if ((region[pc->region].priv & rgnFlagGuarded) && itemById::IsHouse(id) ) // popy { client->sysmessage(" You cannot build houses in town!"); return; } } x = ShortFromCharPtr(buffer[s] +11); //where they targeted y = ShortFromCharPtr(buffer[s] +13); z = ShortFromCharPtr(buffer[s] +15); id_tile = ShortFromCharPtr(buffer[s] +17); z += tileHeight(id_tile); //XAN : House placing fix :) if ( (( x<XBORDER || y <YBORDER ) || ( x>(uint32_t)((map_width*8)-XBORDER) || y >(uint32_t)((map_height*8)-YBORDER) )) ) { client->sysmessage("You cannot build your structure there!"); return; } /* if (ishouse(id1, id2)) // strict checking only for houses ! LB { if(!(CheckBuildSite(x,y,z,sx,sy))) { client->sysmessage("Can not build a house at that location (CBS)!"); return; } }*/ for (k=0;k<sx;k++)//check the SPACEX and SPACEY to make sure they are valid locations.... { for (uint32_t l=0;l<sy;l++) { sLocation loc; loc.x=x+k; loc.y=y+l; loc.z=z; sLocation newpos = sLocation( x+k, y+l, z ); if ( (isWalkable( newpos ) == illegal_z ) && ((charpos.x != x+k)&&(charpos.y != y+l)) ) /*This will take the char making the house out of the space check, be careful you don't build a house on top of your self..... this had to be done So you could extra space around houses, (12+) and they would still be buildable.*/ { client->sysmessage("You cannot build your stucture there."); return; //ConOut("Invalid %i,%i [%i,%i]\n",k,l,x+k,y+l); } //else ConOut("DEBUG: Valid at %i,%i [%i,%i]\n",k,l,x+k,y+l); if ( !norealmulti && cMulti::getAt(loc) ) { client->sysmessage("You cant build structures inside structures"); return; } } } if((id % 256)>=18) sprintf(temp,"%s's house",pc->getCurrentName().c_str());//This will make the little deed item you see when you have showhs on say the person's name, thought it might be helpful for GMs. else strcpy(temp, "a mast"); if(norealmulti) strcpy(temp, name); //--^ if (othername) strcpy(temp,name); if (id == INVALID) return; pItem pHouse = item::CreateFromScript( "$item_hardcoded" ); if ( !pHouse ) return; pHouse->setId( id ); pHouse->setCurrentName( temp ); pc->making=0; pHouse->setPosition(x, y, z); pHouse->setDecay( false ); pHouse->setNewbie( false ); pHouse->setDispellable( false ); pHouse->more4 = itemsdecay; // set to 1 to make items in houses decay pHouse->morex=hdeed; // crackerjack 8/9/99 - for converting back *into* deeds pHouse->setOwner(pc); if (pHouse->isInWorld()) { mapRegions->add(pHouse); } if (!hitem[0] && !boat) { pc->teleport(); return;//If there's no extra items, we don't really need a key, or anything else do we? ;-) } if(boat) { if(!Build(s,pHouse, id%256/*id2*/)) { pHouse->Delete(); return; } } if (i) { pItem pFx1 = MAKE_ITEM_REF( pc->fx1 ); if ( pFx1 != 0 ) pFx1->Delete(); // this will del the deed no matter where it is } pc->fx1=-1; //reset fx1 so it does not interfere // bugfix LB ... was too early reseted pItem pKey=NULL; pItem pKey2=NULL; pItem pBackPack = pc->getBackpack(); //Key... //Altered key naming to include pc's name. Integrated backpack and bankbox handling (Sparhawk) if ((id%256 >=0x70) && (id%256 <=0x73)) { sprintf(temp,"%s's tent key",pc->getCurrentName().c_str()); pKey = item::CreateFromScript( "$item_iron_key", pBackPack ); //iron key for tents pKey2= item::CreateFromScript( "$item_iron_key", pBackPack ); } else if(id%256 <=0x18) { sprintf(temp,"%s's ship key",pc->getCurrentName().c_str()); pKey= item::CreateFromScript( "$item_bronze_key", pBackPack ); //Boats -Rusty Iron Key pKey2= item::CreateFromScript( "$item_bronze_key", pBackPack ); } else { sprintf(temp,"%s's house key",pc->getCurrentName().c_str()); pKey= item::CreateFromScript( "$item_gold_key", pBackPack ); //gold key for everything else; pKey2= item::CreateFromScript( "$item_gold_key", pBackPack ); } if ( ! pKey || ! pKey2 ) return; pKey->Refresh(); pKey2->Refresh(); pHouse->st = pKey->getSerial(); // Create link from house to housekeys to allow easy renaming of pHouse->st2= pKey2->getSerial(); // house, housesign and housekeys without having to loop trough // all world items (Sparhawk) pKey->more = pHouse->getSerial(); //use the house's serial for the more on the key to keep it unique pKey->type=ITYPE_KEY; pKey->setNewbie(); pKey2->more = pHouse->getSerial(); //use the house's serial for the more on the key to keep it unique pKey2->type=ITYPE_KEY; pKey2->setNewbie(); pItem bankbox = pc->GetBankBox(); if(bankbox!=NULL) // we sould add a key in bankbox only if the player has a bankbox =) { pItem p_key3=item::CreateFromScript( "$item_gold_key" ); if ( ! p_key3 ) return; p_key3->setCurrentName( "a house key" ); p_key3->more = pHouse->getSerial(); p_key3->type=ITYPE_KEY; p_key3->setNewbie(); bankbox->AddItem(p_key3); } if(nokey) { pKey->Delete(); // No key for .. nokey items pKey2->Delete(); // No key for .. nokey items } for (k=0;k<icount;k++)//Loop through the HOUSE_ITEMs { cScpIterator* iter = NULL; char script1[1024]; char script2[1024]; sprintf(sect,"SECTION HOUSE ITEM %i",hitem[k]); iter = Scripts::House->getNewIterator(sect); if (iter!=NULL) { pItem pi_l=NULL; loopexit=0; do { iter->parseLine(script1, script2); if (script1[0]!='}') { if (!(strcmp(script1,"ITEM"))) { pi_l=item::CreateScriptItem(s,str2num(script2),0);//This opens the item script... so we gotta keep track of where we are with the other script. if(pi_l) { pi_l->magic=2;//Non-Movebale by default pi_l->setDecay( false ); //since even things in houses decay, no-decay by default pi_l->setNewbie( false ); pi_l->setDispellable( false ); pi_l->setPosition(x, y, z); pi_l->setOwner(pc); // SPARHAWK 2001-01-28 Added House sign naming if (pi_l->IsSign()) if ((id%256 >=0x70) && (id%256<=0x73)) pi_l->setCurrentName("%s's tent",pc->getCurrentName().c_str()); else if (id%256<=0x18) pi_l->setCurrentName("%s's ship",pc->getCurrentName().c_str()); else pi_l->setCurrentName("%s's house",pc->getCurrentName().c_str()); } } if (!(strcmp(script1,"DECAY"))) { if (pi_l) pi_l->setDecay(); } if (!(strcmp(script1,"NODECAY"))) { if (pi_l) pi_l->setDecay( false ); } if (!(strcmp(script1,"PACK")))//put the item in the Builder's Backpack { if (pi_l) pi_l->setContainer(pc->getBackpack()); if (pi_l) pi_l->setPosition("x", rand()%90+31); if (pi_l) pi_l->setPosition("y", rand()%90+31); if (pi_l) pi_l->setPosition("z", 9); } if (!(strcmp(script1,"MOVEABLE"))) { if (pi_l) pi_l->magic=1; } if (!(strcmp(script1,"LOCK")))//lock it with the house key { if (pi_l) pi_l->more = pHouse->getSerial(); } if (!(strcmp(script1,"X")))//offset + or - from the center of the house: { if (pi_l) pi_l->setPosition("x", x+str2num(script2)); } if (!(strcmp(script1,"Y"))) { if (pi_l) pi_l->setPosition("y", y+str2num(script2)); } if (!(strcmp(script1,"Z"))) { if (pi_l) pi_l->setPosition("z", z+str2num(script2)); } } } while ( (strcmp(script1,"}")) && (++loopexit < MAXLOOPS) ); if (pi_l) if (pi_l->isInWorld()) { mapRegions->add(pi_l); } safedelete(iter); } } NxwSocketWrapper sw; sw.fillOnline( pc, false ); for( sw.rewind(); !sw.isEmpty(); sw++ ) { pClient ps_i = sw.getClient(); if(ps_i==NULL) continue; pChar pc_i=ps_i->currChar(); if(pc_i) pc_i->teleport(); } //</Luxor> if (!(norealmulti)) { charpos.x= x+cx; //move char inside house charpos.y= y+cy; charpos.dispz= charpos.z= z+cz; pc->setPosition( charpos ); //ConOut("Z: %i Offset: %i Char: %i Total: %i\n",z,cz,chars[currchar[s]].z,z+cz); pc->teleport(); } } }
void cDragdrop::drop_item(P_CLIENT ps) // Item is dropped { UOXSOCKET s=ps->GetSocket(); // CHARACTER cc=ps->GetCurrChar(); 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 = FindItemBySerial(pp->Iserial); #ifdef debug_dragg if (i!=-1) { sprintf(temp, "%04x %02x %02x %01x %04x i-name: %s EVILDRAG-old: %i\n",pp->Iserial, pp->TxLoc, pp->TyLoc, pp->TzLoc, pp->Tserial, items[i].name, EVILDRAGG[s]); clConsole.send(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, EVILDRAGG[s]); clConsole.send(temp); } #endif if ( (pp->TxLoc==-1) && (pp->TyLoc==-1) && (pp->Tserial==0) && (EVILDRAGG[s]==1) ) { EVILDRAGG[s]=0; #ifdef debug_dragg clConsole.send("Swallow only\n"); #endif return; } // swallow! note: previous evildrag ! else if ( (pp->TxLoc==-1) && (pp->TyLoc==-1) && (pp->Tserial==0) && (EVILDRAGG[s]==0) ) { #ifdef debug_dragg clConsole.send("Bounce & Swallow\n"); #endif item_bounce6(ps, pi); return; } else if ( ( (pp->TxLoc!=-1) && (pp->TyLoc!=-1) && ( pp->Tserial!=-1)) || ( (isItemSerial(pp->Iserial)) && (isItemSerial(pp->Tserial)) ) ) EVILDRAGG[s]=1; // calc new evildrag value else EVILDRAGG[s]=0; } #ifdef debug_dragg else { ITEM i = calcItemFromSer( pp->Iserial ); if (i!=-1) { 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, items[i].name, EVILDRAGG[s]); clConsole.send(temp); } } #endif if ( (buffer[s][10]>=0x40) && (buffer[s][10]!=0xff) ) pack_item(ps,pp); else dump_item(ps,pp); }
// New Class implementation void cDragItems::grabItem( P_CLIENT client ) { // Get our character P_CHAR pChar = client->player(); if( pChar == NULL ) return; // Fetch the grab information SERIAL iSerial = LongFromCharPtr( &buffer[ client->socket() ][ 1 ] ); UI16 amount = ShortFromCharPtr( &buffer[ client->socket() ][ 5 ] ); P_ITEM pItem = FindItemBySerial( iSerial ); if( !pItem ) return; // Are we already dragging an item ? // Bounce it and reject the move // (Logged out while dragging an item) if( client->dragging() ) { bounceItem( client, client->dragging() ); bounceItem( client, pItem, true ); return; } // Do we really want to let him break his meditation // When he picks up an item ? // Maybe a meditation check here ?!? pChar->disturbMed( client->socket() ); // Meditation P_CHAR itemOwner = GetPackOwner( pItem, 64 ); // Try to pick something out of another characters posessions if( itemOwner && ( itemOwner != pChar ) && ( !pChar->Owns( itemOwner ) ) ) { client->sysMessage( QString( "You have to steal the %1 out of %2's posessions." ).arg( pItem->getName() ).arg( itemOwner->name.c_str() ) ); bounceItem( client, pItem, true ); return; } // Check if the user can grab the item if( !pChar->canPickUp( pItem ) ) { client->sysMessage( "You cannot pick that up." ); bounceItem( client, pItem, true ); return; } // The user can't see the item // Basically thats impossible as the client should deny moving the item // if it's not in line of sight but to prevent exploits if( !line_of_sight( client->socket(), pChar->pos, pItem->pos, TREES_BUSHES|WALLS_CHIMNEYS|DOORS|ROOFING_SLANTED|FLOORS_FLAT_ROOFING|LAVA_WATER ) ) { client->sysMessage( "You can't see the item." ); bounceItem( client, pItem, true ); return; } P_ITEM outmostCont = GetOutmostCont( pItem, 64 ); // If it's a trade-window, reset the ack-status if( outmostCont && ( outmostCont->contserial == pChar->serial ) && ( outmostCont->layer() == 0 ) && ( outmostCont->id() == 0x1E5E ) ) { // Get the other sides tradewindow P_ITEM tradeWindow = FindItemBySerial( calcserial( outmostCont->moreb1(), outmostCont->moreb2(), outmostCont->moreb3(), outmostCont->moreb4() ) ); // If one of the trade-windows has the ack-status reset it if( tradeWindow && ( tradeWindow->morez || outmostCont->morez ) ) { tradeWindow->morez = 0; outmostCont->morez = 0; sendtradestatus( tradeWindow, outmostCont ); } } // If the top-most container ( thats important ) is a corpse // and looting is a crime, flag the character criminal. if( outmostCont && outmostCont->corpse() ) { // For each item we take out we loose carma // if the corpse is innocent and not in our guild bool sameGuild = ( GuildCompare( pChar, FindCharBySerial( outmostCont->ownserial ) ) != 0 ); if( ( outmostCont->more2 == 1 ) && !pChar->Owns( outmostCont ) && !sameGuild ) { pChar->karma -= 5; criminal( pChar ); client->sysMessage( "You lost some karma." ); } } // Check if the item is too heavy //if( !pc_currchar->isGMorCounselor() ) //{ //} << Deactivated (DarkStorm) // ==== Grabbing the Item is allowed here ==== // Remove eventual item-bonusses if we're unequipping something if( pItem->layer() > 0 ) { P_CHAR wearer = FindCharBySerial( pItem->contserial ); if( wearer ) wearer->removeItemBonus( pItem ); } // Send the user a pickup sound if we're picking it up // From a container/paperdoll if( !pItem->isInWorld() ) soundeffect( client->socket(), 0x00, 0x57 ); // If we're picking up a specific amount of what we got // Take that into account if( pItem->amount() > 1 ) { UI32 pickedAmount = min( amount, pItem->amount() ); // We only have to split if we're not taking it all if( pickedAmount != pItem->amount() ) { P_ITEM splitItem = new cItem( *pItem ); // Create a new item to pick that up splitItem->SetSerial( cItemsManager::getInstance()->getUnusedSerial() ); splitItem->setAmount( pItem->amount() - pickedAmount ); splitItem->setContSerial( pItem->contserial ); splitItem->SetOwnSerial( pItem->ownserial ); splitItem->SetSpawnSerial( pItem->spawnserial ); // He needs to see the new item RefreshItem( splitItem ); // If we're taking something out of a spawn-region it's spawning "flag" is removed isn't it? pItem->SetSpawnSerial( INVALID_SERIAL ); pItem->setAmount( pickedAmount ); } } pItem->setContSerial( pChar->serial ); pItem->SetMultiSerial( INVALID_SERIAL ); pItem->setLayer( 0x1E ); // It's in the equipment of another character if( itemOwner && ( itemOwner != pChar ) ) { itemOwner->weight -= pItem->getWeight(); statwindow( calcSocketFromChar( itemOwner ), itemOwner ); } // If the item is in the bank or any sell-container it's NOT counted as char-weight bool inBank = ( outmostCont && ( outmostCont->contserial == pChar->serial ) && ( outmostCont->layer() >= 0x1A ) ); // Add the weight if: // - Picked from ground // - Picked out of another character // - Picked out of our bank or any other non-visible container if( ( itemOwner != pChar ) || !inBank ) { pChar->weight += pItem->getWeight(); statwindow( client->socket(), pChar ); } }
void 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); }
/*! \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); } }