void csPacketPartyTellAllMessage::send( NXWCLIENT ps ) { if( ps==NULL ) return; NXWSOCKET s = ps->toInt(); size = headerSize + message->size()*sizeof(UI16)+sizeof(UI16); Xsend( s, getBeginValid(), headerSize ); Xsend( s, *message, true ); }
void csPacketRemovePartyMembers::send( NXWCLIENT ps ) { if( ps==NULL ) return; NXWSOCKET s = ps->toInt(); count = members->size(); size = headerSize + count*sizeof(eSERIAL); Xsend( s, getBeginValid(), headerSize ); std::vector<P_PARTY_MEMBER>::iterator iter( members->begin() ), end( members->end () ); for( ; iter!=end; ++iter ) { eSERIAL b = (*iter)->serial; Xsend( s, &b, sizeof( eSERIAL ) ); } }
void cCharStuff::DeleteChar (P_CHAR pc_k) // Delete character { int j;//,serial; //Zippy lag //int ptr,ci; LongToCharPtr(pc_k->serial, &removeitem[1]); if (pc_k->spawnregion>0 && pc_k->spawnregion<1024) { spawnregion[pc_k->spawnregion].current--; } if (pc_k->spawnserial != INVALID_SERIAL) cspawnsp.remove(pc_k->spawnserial, pc_k->serial); if (pc_k->ownserial != INVALID_SERIAL) cownsp.remove(pc_k->ownserial, pc_k->serial); for (j=0;j<now;j++) { if (perm[j]) Xsend(j, removeitem, 5); } if (pc_k != NULL) mapRegions->Remove(pc_k); // taking it out of mapregions BEFORE x,y changed, LB pc_k->free = true; cCharsManager::getInstance()->deleteChar( pc_k ); }
void csPacketPartyInvite::send( NXWCLIENT ps ) { if( ps==NULL ) return; size=headerSize; Xsend( ps->toInt(), getBeginValid(), headerSize ); }
// sends a page of new readonly book to the client void cBooks::readbook_readonly(UOXSOCKET s, P_ITEM pBook, int p) { unsigned char bookpage[14]="\x66\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x08"; int bytes=0,a,c; char seite[8][33]; char fileName[13]; char line[33]; FILE *file = NULL; sprintf( fileName, "%8x.bok", pBook->serial); file = fopen( fileName, "r+b"); // open existing file for read/write if (file == NULL) return; else { fclose(file); file = NULL; } bytes=13; for (a=1;a<=8;a++) { read_line(pBook, p,a,line); c=strlen(line)+1; strcpy(seite[a-1],line); bytes+=c; } bookpage[1]=bytes>>8; bookpage[2]=bytes%256; LongToCharPtr(pBook->serial, &bookpage[3]); bookpage[9]=p>>8; bookpage[10]=p%256; Xsend(s, bookpage, 13); for (int j=0;j<8;j++) { Xsend(s, seite[j], strlen(seite[j])+1); } }
static void Sndbounce5( NXWSOCKET socket ) { if ( socket >= 0 && socket < now) { unsigned char bounce[2]= { 0x27, 0x00 }; bounce[1] = 5; Xsend(socket, bounce, 2); } }
// opens old (readonly) books == old, bugfixed readbook function void cBooks::openbook_old(UOXSOCKET s, P_ITEM pBook) { unsigned char bookopen[10]="\x93\x40\x01\x02\x03\x00\x00\x00\x02"; //LB 7'th dec 1999, making it client 1.26 complaint unsigned char booktitle[61]="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; unsigned char bookauthor[31]="\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; unsigned long loopexit=0; openscript("misc.scp"); sprintf((char*)temp, "BOOK %i", calcserial(pBook->more1, pBook->more2, pBook->more3, pBook->more4)); if (!i_scripts[misc_script]->find((char*)temp)) { closescript(); return; } LongToCharPtr(pBook->serial, &bookopen[1]); do { read2(); } while ( (strcmp((char*)script1, "PAGES")) && (++loopexit < MAXLOOPS) ); bookopen[8] = (char) str2num(script2); // LB, bugfixing old code loopexit=0; do { read2(); } while ( (strcmp((char*)script1, "TITLE")) && (++loopexit < MAXLOOPS) ); strcpy((char*)(booktitle), script2); loopexit=0; do { read2(); } while ( (strcmp((char*)script1, "AUTHOR")) && (++loopexit < MAXLOOPS) ); strcpy((char*)(bookauthor), script2); Xsend(s, bookopen, 9); // LB, bugfixing of old code Xsend(s, booktitle, 60); Xsend(s, bookauthor, 30); closescript(); }
// TESTED: OKAY (fine fine.. now proove that it really works.. ) // guildtitle(viewing character socket, clicked character) displays players title string, over the name // of clicked character, name color gets calculated from the guild relationship of both players // Called by: textflags() void GuildTitle(int s, P_CHAR pc_player2) { char title[150]; char abbreviation[5]; char guildtype[10]; int tl; if ( pc_player2 == NULL ) return; if ( pc_player2->guildstone() != INVALID_SERIAL && pc_player2->guildtoggle() ) { cGuildStone* pStone = dynamic_cast<cGuildStone*>(FindItemBySerial( pc_player2->guildstone() )); strcpy(abbreviation, pStone->abbreviation.c_str()); if (!(strcmp(abbreviation,""))) strcpy(abbreviation,"none"); switch (pStone->guildType) { case cGuildStone::order: strcpy(guildtype, "Order"); break; case cGuildStone::chaos: strcpy(guildtype, "Chaos"); break; default: break; } if (!pc_player2->guildtitle().isEmpty()) sprintf(title,"[%s, %s] [%s]",pc_player2->guildtitle().latin1(),abbreviation,guildtype); else sprintf(title,"[%s] [%s]",abbreviation, guildtype); tl=44+strlen(title)+1; talk[1]=tl>>8; talk[2]=tl%256; LongToCharPtr(pc_player2->serial, &talk[3]); talk[7]=1; talk[8]=1; talk[9]=0; ShortToCharPtr(pc_player2->emotecolor, &talk[10]); talk[12]=0; talk[13]=3; Xsend(s, talk, 14); Xsend(s, sysname, 30); Xsend(s, title, strlen(title)+1); }
/* ** get data from the client and return it ** run in a child process that was forked off from the main process. */ void process(int sock) { char buf[XIA_MAXBUF + 1]; int n; pid_t pid = getpid(); fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds); #ifdef USE_SELECT struct timeval tv; tv.tv_sec = WAIT_FOR_DATA; tv.tv_usec = 0; #endif while (1) { memset(buf, 0, sizeof(buf)); #ifdef USE_SELECT tv.tv_sec = WAIT_FOR_DATA; tv.tv_usec = 0; if ((n = Xselect(sock + 1, &fds, NULL, NULL, &tv)) < 0) { warn("%5d Select failed, closing...\n", pid); break; } else if (n == 0) { // we timed out, close the socket say("%5d timed out on recv\n", pid); break; } else if (!FD_ISSET(sock, &fds)) { // this shouldn't happen! die(-4, "something is really wrong, exiting\n"); } #endif if ((n = Xrecv(sock, buf, sizeof(buf), 0)) < 0) { warn("Recv error on socket %d, closing connection\n", pid); break; } else if (n == 0) { warn("%d client closed the connection\n", pid); break; } say("%5d received %d bytes\n", pid, n); if ((n = Xsend(sock, buf, n, 0)) < 0) { warn("%5d send error\n", pid); break; } say("%5d sent %d bytes\n", pid, n); } say("%5d closing\n", pid); Xclose(sock); }
int sendCmd(int sock, const char *cmd) { int n; if ((n = Xsend(sock, cmd, strlen(cmd), 0)) < 0) { Xclose(sock); die(-1, "Unable to communicate with the server\n"); } return n; }
int sendCmd(int sock, const char *cmd) { int n; warn("Sending Command: %s \n", cmd); if ((n = Xsend(sock, cmd, strlen(cmd), 0)) < 0) { Xclose(sock); die(-1, "Unable to communicate\n"); } return n; }
// old readbook function void cBooks::readbook_readonly_old(UOXSOCKET s, P_ITEM pBook, int p) { int x, y, pos, j; unsigned char bookpage[14]="\x66\x01\x02\x40\x01\x02\x03\x00\x01\x00\x01\x00\x01"; unsigned long loopexit=0,loopexit2=0; openscript("misc.scp"); sprintf((char*)temp, "BOOK %i", calcserial(pBook->more1, pBook->more2, pBook->more3, pBook->more4)); if (!i_scripts[misc_script]->find((char*)temp)) { closescript(); return; } x=p; do { loopexit=0; do { read2(); } while ( (strcmp((char*)script1, "PAGE")) && (++loopexit < MAXLOOPS) ); x--; } while ( (x>0) && (++loopexit2 < 6666 )); closescript(); openscript("misc.scp"); sprintf((char*)temp, "PAGE %s", script2); if (!i_scripts[misc_script]->find((char*)temp)) { closescript(); return; } pos=ftell(scpfile); x=-1; y=-2; loopexit=0; do { read1(); x++; y+=strlen((char*)script1)+1; } while ( (strcmp((char*)script1, "}")) && (++loopexit < MAXLOOPS) ); y+=13; fseek(scpfile, pos, SEEK_SET); bookpage[1]=y>>8; bookpage[2]=y%256; LongToCharPtr(pBook->serial, &bookpage[3]); bookpage[9]=p>>8; bookpage[10]=p%256; bookpage[11]=x>>8; bookpage[12]=x%256; Xsend(s, bookpage, 13); for (j=0;j<x;j++) { read1(); Xsend(s, script1, strlen((char*)script1)+1); } closescript(); }
void cPacketStatWindow::sendExtended( NXWCLIENT ps ) { if( ps == NULL ) return; //after error here sendBasic( ps, 0x03 ); Xsend( ps->toInt(), (char*)(&this->sex), 0x1B ); };
// opens new books // writeable 1 -> open new books in writable mode // 0 -> open new books in readonly mode void cBooks::openbook_new(UOXSOCKET s, P_ITEM pBook, char writeable) { unsigned char bookopen[10]= "\x93\x40\x01\x02\x03\x01\x01\x00\x02"; //LB 7'th dec 1999, making it client 1.26 complaint int a,b; short pages, bytes; char line[33]; char buch[256][8][33]; char fileName[13]; bool bookexists = false; FILE *file; // I dont know what that new client 1.26 byte does, but it needs to be set to 1 or 2 or writing doesnt work // wild guess: rune books ... char booktitle[61]={0x00,}; char bookauthor[31]={0x00,}; sprintf( fileName, "%8x.bok", pBook->serial); file = fopen( fileName, "r+b"); // open existing file for read/write bookexists = (file!=NULL); if (bookexists) { fclose(file); file = NULL; read_author ( pBook, bookauthor ); // fetch author if existing read_title ( pBook, booktitle ); // fetch title if existing pages = read_number_of_pages(pBook); } else { pages = pBook->morey; // if new book get number of maxpages ... if (pages<1 || pages>255) pages = 16; } // clear all buffers from previous book openings memset( &authorbuffer[s], '~', 32 ); memset( &titlebuffer[s], '~', 62 ); memset( &pagebuffer[s], '~', 511 ); LongToCharPtr(pBook->serial, &bookopen[1]); ShortToCharPtr(pages, &bookopen[7]); if (writeable) bookopen[5] = 1; else bookopen[5] = 0; Xsend(s, bookopen, 9); Xsend(s, booktitle, 60); Xsend(s, bookauthor, 30); if (!bookexists) return; // dont send book contents if the file doesnt exist (yet)! if (!writeable) return; // if readonly book return !! ////////////////////////////////////////////////////////////// // Now we HAVE to send the ENTIRE Book / / // Cauz in writeable mode the client only sends out packets / // if something gets changed / // this also means -> for each bookopening in writeable mode / // lots of data has to be send. / ////////////////////////////////////////////////////////////// unsigned char bookpage_pre[10]="\x66\x01\x02\x40\x01\x02\x03\x00\x01"; unsigned char bookpage[5]="\x00\x00\x00\x08"; // we have to know the total size "in advance" // thats why i save the book data in a temporaray array to // avoid reading it twice from (slow) hd bytes = 9; for (a = 1; a <= pages; a++) { bytes+=4; // 4 bytes for each page for (b=1;b<=8;b++) { read_line(pBook, a,b, line); strcpy(buch[a-1][b-1],line); bytes += static_cast<short>(strlen(line)+1); // plus the stringlength+null terminator per(!) row } } ShortToCharPtr(bytes, &bookpage_pre[1]); LongToCharPtr(pBook->serial, &bookpage_pre[3]); ShortToCharPtr(pages, &bookpage_pre[7]); Xsend(s, bookpage_pre, 9); for (a=1;a<=pages;a++) { ShortToCharPtr(a, &bookpage[0]); Xsend(s, bookpage, 4); for (int j=0;j<8;j++) { Xsend(s, buch[a-1][j], strlen(buch[a-1][j])+1); } } }
int main(int argc, char **argv) { struct addrinfo *ai; sockaddr_x *sa; int seq = 0; // FIXME: put signal handlers back into code once Xselect is working // signal(SIGINT, handler); // signal(SIGTERM, handler); getConfig(argc, argv); if (Xgetaddrinfo(NAME, NULL, NULL, &ai) < 0) die("Unable to lookup address for %s\n", NAME); sa = (sockaddr_x*)ai->ai_addr; if ((sock = Xsocket(AF_XIA, SOCK_STREAM, 0)) < 0) die("Unable to create a socket\n"); say("Opening firehose: %s\n", NAME); if (Xconnect(sock, (struct sockaddr*)sa, sizeof(sockaddr_x)) < 0) { Xclose(sock); die("Unable to connect to %s\n", NAME); } // tell firehose how many packets we expect if (Xsend(sock, &fhc, sizeof(fhc), 0) < 0) { Xclose(sock); die("Unable to send config information to the firehose\n"); } int count = 0; char *buf = (char *)malloc(pktSize); while (!timetodie) { int n; fd_set fds; FD_ZERO(&fds); FD_SET(sock, &fds); struct timeval tv; tv.tv_sec = 2; tv.tv_usec = 0; if ((n = Xselect(sock + 1, &fds, NULL, NULL, &tv)) < 0) { printf("select failed\n"); break; } else if (n == 0) { printf("recv timeout\n"); break; } else if (!FD_ISSET(sock, &fds)) { // this shouldn't happen! printf("something is really wrong, exiting\n"); break; } int rc = Xrecv(sock, buf, sizeof(buf), 0); if (rc < 0) die("Receive failure\n"); memcpy(&seq, buf, sizeof(int)); say("expecting %d, got %d", count, seq); if (count == seq) say("\n"); else say(" lost %d\n", seq - count); count++; if (count == numPkts) break; if (delay) usleep(delay); } seq++; if (count != seq) printf("lost %d packets, received %d, expected %d\n", seq - count, count, seq); else printf("success!\n"); Xclose(sock); }
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::buyaction(int s) { char clearmsg[8]; int clear, i, j; P_ITEM buyit[256]; int amount[512]; int layer[512]; int playergoldtotal; int goldtotal; int itemtotal; int soldout; int tmpvalue=0; // Fixed for adv trade system -- Magius(CHE) § // CHARACTER cc=currchar[s]; P_CHAR pc_currchar = currchar[s]; P_ITEM pi_pack = Packitem(pc_currchar); if (pi_pack == NULL) return; //LB no player-pack - no buy action possible - and no crash too ;-) P_CHAR npc = FindCharBySerial(calcserial(buffer[s][3], buffer[s][4], buffer[s][5], buffer[s][6])); if (npc <= 0) return; clear=0; goldtotal=0; soldout=0; itemtotal=(((256*(buffer[s][1]))+buffer[s][2])-8)/7; if (itemtotal>256) return; //LB for(i = 0; i < itemtotal; i++) { layer[i]=buffer[s][8+(7*i)]; buyit[i] = FindItemBySerial(calcserial(buffer[s][8+(7*i)+1], buffer[s][8+(7*i)+2], buffer[s][8+(7*i)+3], buffer[s][8+(7*i)+4])); amount[i]=(256*(buffer[s][8+(7*i)+5]))+buffer[s][8+(7*i)+6]; if (buyit[i] != NULL) { buyit[i]->rank=10; // Fixed for adv trade system -- Magius(CHE) § tmpvalue = buyit[i]->value; tmpvalue = calcValue(buyit[i], tmpvalue); if (SrvParams->trade_system()==1) tmpvalue = calcGoodValue(pc_currchar, buyit[i], tmpvalue,0); goldtotal += (amount[i]*tmpvalue); // End Fix for adv trade system -- Magius(CHE) § } } bool useBank; useBank = (goldtotal >= SrvParams->checkBank() ); if( useBank ) playergoldtotal = GetBankCount( pc_currchar, 0x0EED ); else playergoldtotal = pc_currchar->CountGold(); if ((playergoldtotal>=goldtotal)||(pc_currchar->isGM())) { for (i = 0; i < itemtotal; i++) { if (buyit[i] != NULL) { if (buyit[i]->amount < amount[i]) { soldout = 1; } } } if (soldout) { npctalk(s, npc, "Alas, I no longer have all those goods in stock. Let me know if there is something else thou wouldst buy.",0); clear = 1; } else { if (pc_currchar->isGM()) { sprintf((char*)temp, "Here you are, %s. Someone as special as thee will receive my wares for free of course.", pc_currchar->name.c_str()); } else { if(useBank) { sprintf((char*)temp, "Here you are, %s. %d gold coin%s will be deducted from your bank account. I thank thee for thy business.", pc_currchar->name.c_str(), goldtotal, (goldtotal==1) ? "" : "s"); goldsfx(s, goldtotal); } else { sprintf((char*)temp, "Here you are, %s. That will be %d gold coin%s. I thank thee for thy business.", pc_currchar->name.c_str(), goldtotal, (goldtotal==1) ? "" : "s"); goldsfx(s, goldtotal); // Dupois, SFX for gold movement. Added Oct 08, 1998 } } npctalkall(npc, (char*)temp, 0); npcaction(npc, 0x20); // bow (Duke, 17.3.2001) clear = 1; if( !(pc_currchar->isGM() ) ) { if( useBank ) DeleBankItem( pc_currchar, 0x0EED, 0, goldtotal ); else delequan( pc_currchar, 0x0EED, goldtotal, NULL ); } for (i=0;i<itemtotal;i++) { P_ITEM pi = buyit[i]; if (pi != NULL) { if (pi->amount>amount[i]) { if (pi->pileable) { Commands->DupeItem(s, buyit[i], amount[i]); } else { for (j=0;j<amount[i];j++) { Commands->DupeItem(s, buyit[i], 1); } } pi->amount-=amount[i]; pi->restock+=amount[i]; } else { switch(layer[i]) { case 0x1A: if (pi->pileable) { Commands->DupeItem(s, buyit[i], amount[i]); } else { for (j=0;j<amount[i];j++) { Commands->DupeItem(s, buyit[i], 1); } } pi->amount=pi->amount-amount[i]; pi->restock=pi->restock+amount[i]; break; case 0x1B: if (pi->pileable) { pi->SetContSerial(pi_pack->serial); RefreshItem(buyit[i]);//AntiChrist } else { for (j=0;j<amount[i]-1;j++) { Commands->DupeItem(s, buyit[i], 1); } pi->SetContSerial(pi_pack->serial); pi->amount = 1; RefreshItem(buyit[i]);//AntiChrist } break; default: clConsole.send("ERROR: Fallout of switch statement without default. wolfpack.cpp, buyaction()\n"); //Morrolan } } } } } } else { npctalkall(npc, "Alas, thou dost not possess sufficient gold for this purchase!",0); } if (clear) { 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); } Weight->NewCalc(pc_currchar); // Ison 2-20-99 statwindow(s, pc_currchar); }
void process(int peer) { fhConfig fhc; char *buf = NULL; uint32_t count = 0; int n; signal(SIGINT, handler); fd_set fds; FD_ZERO(&fds); FD_SET(peer, &fds); struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; n = Xselect(peer + 1, &fds, NULL, NULL, &tv); if (n < 0) { printf("select failed\n"); goto done; } else if (n == 0) { printf("recv timeout\n"); goto done; } else if (!FD_ISSET(peer, &fds)) { // this shouldn't happen! printf("something is really wrong, exiting\n"); goto done; } if (Xrecv(peer, &fhc, sizeof(fhc), 0) < 0) { printf("Unable to get configuration block\n"); goto done; } fhc.numPkts = ntohl(fhc.numPkts); fhc.delay = ntohl(fhc.delay); fhc.pktSize = ntohl(fhc.pktSize); // need to have at least enough room for the sequence # fhc.pktSize = MAX(fhc.pktSize, sizeof(unsigned)); if (fhc.numPkts == 0) say("packet count = non-stop\n"); else say("packet count = %d\n", fhc.numPkts); say("packet size = %d\n", fhc.pktSize); say("inter-packet delay = %d\n", fhc.delay); if (!(buf = (char *)malloc(fhc.pktSize))) { printf("Memory error\n"); goto done; } while (!timetodie) { if (fhc.numPkts > 0 && count == fhc.numPkts) break; printf("sending packet %d\n", count); data(count, buf, sizeof(buf)); Xsend(peer, buf, sizeof(buf), 0); count++; if (fhc.delay != 0) usleep(fhc.delay); } done: say("done\n"); if (buf) free(buf); Xclose(peer); }
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); }
void cDragdrop::get_item(P_CLIENT ps) // Client grabs an item { int npc=-1, amount, update = 0, serial; UOXSOCKET s = ps->GetSocket(); int cc = ps->GetCurrChar(); P_CHAR pc_currchar = MAKE_CHARREF_LR(cc); serial = calcserial(buffer[s][1], buffer[s][2], buffer[s][3], buffer[s][4]); if (serial == INVALID_SERIAL || buffer[s][1] < 0x40) return; // landscape or a character P_ITEM pi = FindItemBySerial(serial); if (pi == NULL) return; pc_currchar->disturbMed(s); // Meditation // Zippy's stealing changes P_ITEM px = pi; if (!px->isInWorld()) // Find character owning item { unsigned long loopexit = 0; do // Find character owning item { if (isCharSerial(px->contserial)) { npc = calcCharFromSer(px->contserial); } else // its an item { if (px->isInWorld()) { npc=-1; break; } px = FindItemBySerial(px->contserial); // ANTICHRIST -- SECURE TRADE FIX if (px != NULL) // LB overwriting x is essential here, dont change it!!! { if (px->layer == 0 && px->id() == 0x1E5E) { // Trade window??? serial = calcserial(px->moreb1, px->moreb2, px->moreb3, px->moreb4); if (serial == INVALID_SERIAL) return; P_ITEM pi_z = FindItemBySerial(serial); if ( pi_z != NULL ) if ((pi_z->morez || px->morez)) { pi_z->morez = 0; px->morez = 0; sendtradestatus(pi_z, px); } } // Blackwinds Looting is crime implementation // changed slightly by Ripper if (px->corpse != 0 && !pc_currchar->Owns(px)) { P_CHAR co = FindCharBySerial(px->ownserial); if (px->more2 == 1 && Guilds->Compare(DEREF_P_CHAR(pc_currchar), DEREF_P_CHAR(co)) == 0) { pc_currchar->karma -= 5; criminal(DEREF_P_CHAR(pc_currchar)); sysmessage(s, "You lost some karma!"); } npc = 0; } // Criminal stuff if (px->corpse != 0) npc = 0; } // end if x!=-1 if (px == NULL) npc = 0; } } while ((npc==-1) &&(++loopexit < MAXLOOPS)); } if (npc>0) // 0=corpse, hence >0 .. { if (!(pc_currchar->isGM()) && npc != DEREF_P_CHAR(pc_currchar) && ! pc_currchar->Owns(&chars[npc])) {// Own serial stuff by Zippy -^ Pack aniamls and vendors. bounce[1] = 0; Xsend(s, bounce, 2); if (ps->IsDragging()) { ps->ResetDragging(); item_bounce3(pi); pi->magic = 3; } return; } } // End Zippy's change // Boats-> if (px != NULL && npc!=-1) { if (px->multis>0) imultisp.remove(px->multis, px->serial); px->startDecay(); // End Boats Change // AntiChrist -- for poisoned items if (px->layer>0) { chars[npc].removeItemBonus(px); // remove BONUS STATS given by equipped special items } if ((px->trigon==1) && (px->layer != 0) && (px->layer != 15) && (px->layer < 19))// -Frazurbluu- Trigger Type 2 is my new trigger type *- { Trig->triggerwitem(s, pi, 1); // trigger is fired } } if (pi != NULL) { if (pi->corpse != 1) { UpdateStatusWindow(s, pi); if (!pc_currchar->canPickUp(pi)) { bounce[1] = 0; Xsend(s, bounce, 2); if (ps->IsDragging()) // only restore item if it got draggged before !!! { ps->ResetDragging(); item_bounce4(s, pi); } } else { // AntiChrist bugfix for the bad bouncing bug ( disappearing items when bouncing ) DRAGGED[s] = 1; pi->oldx = pi->pos.x; // first let's save the position pi->oldy = pi->pos.y; pi->oldz = pi->pos.z; pi->oldcontserial = pi->contserial; // then let's save the container pi->oldlayer = pi->layer; // then the layer pi->layer = 0; if (!pi->isInWorld()) soundeffect(s, 0x00, 0x57); if (pi->amount>1) { amount = (buffer[s][5] << 8) + buffer[s][6]; if (amount>pi->amount) amount = pi->amount; if (amount < pi->amount) { P_ITEM pi_c = Items->MemItemFree(); // pi_c->Init(0); #pragma note("Replace by a copy constructor before finishing items[]") memcpy(pi_c, pi, sizeof(cItem)); // Tauriel reduce code faster too pi_c->SetSerial(cItemsManager::getItemsManager().getUnusedSerial()); pi_c->amount = pi->amount - amount; pi_c->SetContSerial(pi_c->contserial); pi_c->SetOwnSerial(pi_c->ownserial); pi_c->SetSpawnSerial(pi_c->spawnserial); statwindow(s,DEREF_P_CHAR(pc_currchar)); RefreshItem(pi_c);//AntiChrist } if (pi->id() == 0x0EED) // gold coin { P_ITEM packnum = packitem(currchar[s]); if (packnum != NULL) // lb if (pi->contserial == packnum->serial) update = 1; } pi->amount = amount; } /* int amt = 0, wgt; bool tooheavy=false; wgt = (int)Weight->LockeddownWeight(pi, &amt, 0); if(pi->contserial>0) { if (( (pc_currchar->weight+wgt) > (pc_currchar->st*WEIGHT_PER_STR)+30)) // LB -> added: drop item if too heavy { float res=float( (pc_currchar->weight+wgt) - ((pc_currchar->st*WEIGHT_PER_STR)+30))*2; int diff = pc_currchar->st; diff -= (int)res; if (diff<=0 && !pc_currchar->isGM() ) { tooheavy=true; bounce[1] = 0; Xsend(s, bounce, 2); if (ps->IsDragging()) // only restore item if it got dragged before !!! { ps->ResetDragging(); item_bounce4(s, pi); } sysmessage(s, "you can't pick this up, this is too heavy"); return; } } } if (!tooheavy) pc_currchar->weight+=wgt; update = 1; */ // LB remark: drop item if too heavy is a good solution, // but there's still a small bug remaining. // added weight from items picked up, but not put to bp, pd, in other words hold in ones hand, // is NOT subtracted when being dropped again to ground/other chars/other chars' bp's. // but this bug doesnt show up becasue weight is re-calculated automatically all 10 secs. // without adding weight of the item curently carrying in hand. // a correct solutions need the weight of item in hand being stored // , added to auto-re-calculation all x-secs code, and being subtracted if dropped. // because it's now only happening for leight weight items, because heavy weight itms cant be picke up anymore // I haven't corrected this yet. // Tauriel remove item from world mapcells mapRegions->Remove(pi); // remove this item from a map cell pi->pos.x = 0; pi->pos.y = 0; pi->pos.z = 0; pi->flags.isBeeingDragged=true; pi->SetContSerial(-1); } } } // end of if i!=-1 if (update) statwindow(s, DEREF_P_CHAR(pc_currchar)); }
void *recvCmd (void *socketid) { int i, n, count = 0; ChunkInfo *info = NULL; char command[XIA_MAXBUF]; char reply[XIA_MAXBUF]; int sock = *((int*)socketid); char *fname; //ChunkContext contains size, ttl, policy, and contextID which for now is PID ChunkContext *ctx = XallocCacheSlice(POLICY_FIFO|POLICY_REMOVE_ON_EXIT, 0, 20000000); if (ctx == NULL) die(-2, "Unable to initilize the chunking system\n"); while (1) { say("waiting for server command\n"); memset(command, '\0', strlen(command)); memset(reply, '\0', strlen(reply)); if ((n = Xrecv(sock, command, 1024, 0)) < 0) { warn("socket error while waiting for data, closing connection\n"); break; } //Sender does the chunking and then should start the sending commands if (strncmp(command, "get", 3) == 0) { fname = &command[4]; say("Server requested file %s\n", fname); if (info) { // clean up the existing chunks first } info = NULL; count = 0; say("chunking file %s\n", fname); //Chunking is done by the XputFile which itself uses XputChunk, and fills out the info if ((count = XputFile(ctx, fname, CHUNKSIZE, &info)) < 0) { warn("unable to serve the file: %s\n", fname); sprintf(reply, "FAIL: File (%s) not found", fname); } else { sprintf(reply, "OK: %d", count); } say("%s\n", reply); //Just tells the receiver how many chunks it should expect. if (Xsend(sock, reply, strlen(reply), 0) < 0) { warn("unable to send reply to client\n"); break; } //Sending the blocks cids } else if (strncmp(command, "block", 5) == 0) { char *start = &command[6]; char *end = strchr(start, ':'); if (!end) { // we have an invalid command, return error to client sprintf(reply, "FAIL: invalid block command"); } else { *end = 0; end++; // FIXME: clean up naming, e is now a count int s = atoi(start); int e = s + atoi(end); strcpy(reply, "OK:"); for(i = s; i < e && i < count; i++) { strcat(reply, " "); strcat(reply, info[i].cid); } } printf("%s\n", reply); if (Xsend(sock, reply, strlen(reply), 0) < 0) { warn("unable to send reply to client\n"); break; } } else if (strncmp(command, "done", 4) == 0) { say("done sending file: removing the chunks from the cache\n"); for (int i = 0; i < count; i++) XremoveChunk(ctx, info[i].cid); XfreeChunkInfo(info); info = NULL; count = 0; break; } else { sprintf(reply, "FAIL: invalid command (%s)\n", command); warn(reply); if (Xsend(sock, reply, strlen(reply), 0) < 0) { warn("unable to send reply to client\n"); break; } } } if (info) XfreeChunkInfo(info); XfreeCacheSlice(ctx); return (void *)1; }
void cBoat::Move(UOXSOCKET s, int dir, P_ITEM pBoat) {//Move the boat and all it's items 1 square int tx=0,ty=0; int serial; if (pBoat == NULL) return; serial = calcserial(pBoat->moreb1, pBoat->moreb2, pBoat->moreb3, pBoat->moreb4); if (serial == INVALID_SERIAL) return; P_ITEM pTiller = FindItemBySerial( serial ); if(pTiller == NULL) return; P_ITEM pi_p1 = FindItemBySerial( pBoat->morex ); if(pi_p1 == NULL) return; P_ITEM pi_p2 = FindItemBySerial( pBoat->morey ); if(pi_p2 == NULL) return; P_ITEM pHold = FindItemBySerial( pBoat->morez ); if(pHold == NULL) return; Xsend(s,wppause,2); switch(dir&0x0F)//Which DIR is it going in? { case '\x00' : ty--; break; case '\x01' : tx++; ty--; break; case '\x02' : tx++; break; case '\x03' : tx++; ty++; break; case '\x04' : ty++; break; case '\x05' : tx--; ty++; break; case '\x06' : tx--; break; case '\x07' : tx--; ty--; break; default: { sprintf((char*)temp,"warning: Boat direction error: %i int boat %i\n",pBoat->dir&0x0F,pBoat->serial); LogWarning((char*)temp); break; } } if((pBoat->pos.x+tx<=200 || pBoat->pos.x+tx>=6000) && (pBoat->pos.y+ty<=200 || pBoat->pos.y+ty>=4900)) //bugfix LB { pBoat->type2=0; itemtalk(s, pTiller, "Arr, Sir, we've hit rough waters!"); Xsend(s,restart,2); return; } if(Block(pBoat,tx,ty,dir)) { pBoat->type2=0; itemtalk(s, pTiller, "Arr, somethings in the way!"); Xsend(s,restart,2); return; } //Move all the special items Coord_cl desloc(tx, ty, 0); pBoat->moveTo(pBoat->pos + desloc); pTiller->moveTo(pTiller->pos + desloc); pi_p1->moveTo(pi_p1->pos + desloc); pi_p2->moveTo(pi_p2->pos + desloc); pHold->moveTo(pHold->pos + desloc); serial = pBoat->serial; unsigned int a; vector<SERIAL> vecEntries = imultisp.getData(pBoat->serial); for (a = 0; a < vecEntries.size(); a++) { P_ITEM pi = FindItemBySerial(vecEntries[a]); if(pi != NULL) { pi->MoveTo(pi->pos.x+=tx, pi->pos.y+=ty, pi->pos.z); sendinrange(pi); } } vecEntries.clear(); vecEntries = cmultisp.getData(pBoat->serial); for (a = 0; a < vecEntries.size(); a++) { P_CHAR pc_c = FindCharBySerial(vecEntries[a]); if (pc_c != NULL) { pc_c->moveTo(pc_c->pos + desloc); teleport((pc_c)); } } Xsend(s,restart,2); }
void cDragdrop::wear_item(P_CLIENT ps) // Item is dropped on paperdoll { int j, k; tile_st tile; int serial, serhash, ci, letsbounce=0; // AntiChrist (5) - new ITEMHAND system UOXSOCKET s=ps->GetSocket(); int cc=ps->GetCurrChar(); P_CHAR pc_currchar = MAKE_CHARREF_LR(cc); int cserial=calcserial(buffer[s][6],buffer[s][7],buffer[s][8],buffer[s][9]); if(cserial==-1) return; k=calcCharFromSer( cserial ); if( chars[k].dead ) //Exploit fix: Dead ppl can't equip anything. return; P_ITEM pi=FindItemBySerPtr(buffer[s]+1); if (!pi) return; pi->flags.isBeeingDragged=false; // if (clientDimension[s]==3) // { Map->SeekTile(pi->id(), &tile); // sprintf(temp, "Tiledata: name: %s flag1: %i flag2: %i flag3: %i flag4: %i layer: %i\n", tile.name, tile.flag1, tile.flag2, tile.flag3, tile.flag4, tile.layer); // clConsole.send(temp); if (tile.layer==0) { sysmessage(s,"You can't wear that"); Sndbounce5(s); if (ps->IsDragging()) { ps->ResetDragging(); item_bounce4(s,pi); UpdateStatusWindow(s,pi); } return; } // } if (pi->id1>=0x40) return; // LB, client crashfix if multi-objects are moved to PD if (k==DEREF_P_CHAR(pc_currchar) || pc_currchar->isGM()) { if (k!=-1) //lb if (k==DEREF_P_CHAR(pc_currchar) && pi->st>chars[k].st) { sysmessage(s,"You are not strong enough to use that."); Sndbounce5(s); if (ps->IsDragging()) { ps->ResetDragging(); item_bounce4(s,pi); UpdateStatusWindow(s,pi); } return; } if (pc_currchar->id1==0x01 && pc_currchar->id2==0x90) // Ripper...so males cant wear female armor if (pi->id1==0x1c && ( pi->id2==0x00 || pi->id2==0x02 || pi->id2==0x04 || pi->id2==0x06 || pi->id2==0x08 || pi->id2==0x0a || pi->id2==0x0c)) { sysmessage(s,"You cant wear female armor!"); Sndbounce5(s); if (ps->IsDragging()) { ps->ResetDragging(); item_bounce4(s,pi); UpdateStatusWindow(s,pi); } return; } // if (clientDimension[s]==2) Map->SeekTile(pi->id(), &tile); if ((((pi->magic==2)||((tile.weight==255)&&(pi->magic!=1)))&&((pc_currchar->priv2&1)==0)) || ( (pi->magic==3|| pi->magic==4) && !pc_currchar->Owns(pi))) { item_bounce6(ps,pi); return; } // - AntiChrist (4) - checks for new ITEMHAND system // - now you can't equip 2 hnd weapons with 1hnd weapons nor shields!! serial=pc_currchar->serial; vector<SERIAL> vecContainer = contsp.getData(serial); for (ci=0;ci<vecContainer.size();ci++) { P_ITEM pi2 = FindItemBySerial(vecContainer[ci]); if (pi2 != NULL && pi2->contserial == serial) { if (pi2->itmhand==1 && pi->itmhand==1) { sysmessage(s,"You already have a weapon equipped!"); letsbounce=1; } else if (pi2->itmhand==2 && pi->itmhand==1) { sysmessage(s,"Your hands are both occupied!"); letsbounce=1; } else if (pi2->itmhand==1 && pi->itmhand==2) { sysmessage(s,"You cannot equip a two handed weapon with a weapon equipped!"); letsbounce=1; } else if (pi2->itmhand==2 && pi->itmhand==2) { sysmessage(s,"You cannot equip a two handed weapon with a two handed weapon equipped!"); letsbounce=1; } else if (pi2->itmhand==2 && pi->itmhand==3) { sysmessage(s,"You cannot equip a shield with a two handed weapon equipped!"); letsbounce=1; } else if (pi2->itmhand==3 && pi->itmhand==2) { sysmessage(s,"You cannot equip a two handed weapon with a shield equipped!"); letsbounce=1; } else if (pi2->layer == tile.layer) { sysmessage(s, "You already have an armor equipped!"); letsbounce = 1; } } if(letsbounce)//Let's bounce the item { Sndbounce5(s); if (ps->IsDragging()) { ps->ResetDragging(); item_bounce4(s,pi); UpdateStatusWindow(s,pi); itemsfx(s, pi->id()); // antichrist } return; } } if (!(pc_currchar->isGM())) //Ripper..players cant equip items on other players or npc`s paperdolls. { if ((k != DEREF_P_CHAR(pc_currchar)) && (!chars[k].isNpc())) { sysmessage(s, "You cant put items on other players!"); item_bounce6(ps,pi); return; } } pi->SetContSerial(LongFromCharPtr(buffer[s]+6)); pi->layer=buffer[s][5]; // AntiChrist - now the STAT BONUS works - pc_currchar->st = (pc_currchar->st + pi->st2); pc_currchar->chgDex(pi->dx2); pc_currchar->in = (pc_currchar->in + pi->in2); if (pi->trigtype==2) // -Frazurbluu- Trigger Type 2 is my new trigger type *- { Trig->triggerwitem(s, pi, 1); // trigger is fired } // AntiChrist -- for poisoned items if (showlayer) clConsole.send("Item equipped on layer %i.\n",pi->layer); SndRemoveitem(pi->serial); LongToCharPtr(pi->serial,wearitem+1); ShortToCharPtr(pi->id(),wearitem+5); wearitem[8]=pi->layer; LongToCharPtr(pi->contserial,wearitem+9); wearitem[13]=pi->color1; wearitem[14]=pi->color2; Xsend(s, wearitem, 15); wornitems(s, k);//send update to current socket // -Frazurbluu- Worn item triggers will need code here // Trigger cod ewill also need the adjustments made for skill adding // An apply/unapply type of variable must be added for skill gains // Spell Item will have to be considered, like a necklace of reflection for (j=0;j<now;j++) { if (perm[j] && inrange1p(k, currchar[j]) && (j!=s))//and to all inrange sockets (without re-sending to current socket)//AntiChrist wornitems(j, k); } itemsfx(s, pi->id()); // Dupois - see itemsfx() for details // Added Oct 09, 1998 Weight->NewCalc(DEREF_P_CHAR(pc_currchar)); // Ison 2-20-99 statwindow(s,DEREF_P_CHAR(pc_currchar)); if (pi->glow>0) { pc_currchar->removeHalo(pi); // if gm equips on differnt player it needs to be deleted out of the hashteble chars[k].addHalo(pi); chars[k].glowHalo(pi); } } }
/** * @brief Initiate an XSSL connection with server. * * @param xssl * * @return 1 on success, <1 on failure */ int XSSL_connect(XSSL *xssl) { char buf[XIA_MAXBUF]; int n; /* Send CLIENT HELLO */ sprintf(buf, "CLIENT HELLO"); if ((n = Xsend(xssl->sockfd, buf, strlen(buf), 0)) != strlen(buf)) { ERROR("ERROR sending CLIENT HELLO"); return 0; } /* Wait for SERVER HELLO */ // Receive public key + temporary public key signed by server's long-term private key // Continue receiving until we see "SERVER DONE" int offset = 0; while ( offset < 11 || strcmp("SERVER DONE", &buf[offset-11]) != 0 ) { n = Xrecv(xssl->sockfd, &buf[offset], sizeof(buf)-offset, 0); if (n < 0) { ERROR("ERROR receiving SERVER HELLO"); return n; } if (n == 0) { ERROR("ERROR: server closed connection during SERVER HELLO"); return n; } offset += n; } /* Parse public keys from SERVER HELLO */ offset = strlen("SERVER HELLO"); char *keys = &buf[offset]; // start of signed portion of message uint32_t *keybufsizeptr = (uint32_t*)&buf[offset]; uint32_t keybufsize = *keybufsizeptr; // TODO: error checking here offset += sizeof(uint32_t); RSA *pubkey = deserialize_rsa_pub_key(&buf[offset], keybufsize); offset += keybufsize; uint32_t *tempkeybufsizeptr = (uint32_t*)&buf[offset]; uint32_t tempkeybufsize = *tempkeybufsizeptr; offset += sizeof(uint32_t); RSA *sessionPubkey = deserialize_rsa_pub_key(&buf[offset], tempkeybufsize); offset += tempkeybufsize; uint32_t *siglenptr = (uint32_t*)&buf[offset]; uint32_t siglen = *siglenptr; offset += sizeof(uint32_t); char* sig = &buf[offset]; offset += siglen; DBGF("Received keys:\n\tkeylen: %d\n\ttempkeylen: %d\n\tsiglen: %d", keybufsize, tempkeybufsize, siglen); /* Verify two things: * 1) hash(key) == SID so we trust the signature * 2) verify the sig so we trust the temp key */ sockaddr_x *sa = (sockaddr_x*)malloc(sizeof(sockaddr_x)); socklen_t len = sizeof(sockaddr_x); if (Xgetpeername(xssl->sockfd, (struct sockaddr*)sa, &len) < 0) { ERRORF("Error in Xgetpeername on socket %d: %s", xssl->sockfd, strerror(errno)); return 0; } Graph g(sa); Node sid_node = g.get_final_intent(); DBGF("SID: %s", sid_node.to_string().c_str()); char *sid_from_key_hash = SID_from_keypair(pubkey); DBGF("Pub key hash: %s", sid_from_key_hash); if (strcmp(sid_node.to_string().c_str(), sid_from_key_hash) != 0) { WARN("Hash of received public key does not match SID! Closing connection."); return 0; } if (verify(pubkey, keys, keybufsize+tempkeybufsize+2*sizeof(uint32_t), sig, siglen) != 1) { WARN("Unable to verify signature on temporary RSA keypair! Closing connection."); return 0; } /* Generate pre-master secret and send to server, encrypted with sessionPubKey */ unsigned char* pms = (unsigned char*)malloc(PRE_MASTER_SECRET_LENGTH); if (RAND_bytes(pms, PRE_MASTER_SECRET_LENGTH) != 1) { ERROR("ERROR: Couldn't generate pre-master secret"); return 0; } if (VERBOSITY >= V_DEBUG) { DBG("Pre-Master Secret:"); print_bytes(pms, PRE_MASTER_SECRET_LENGTH); } int ciphertext_len; if ( (ciphertext_len = pub_encrypt(sessionPubkey, pms, PRE_MASTER_SECRET_LENGTH, buf, XIA_MAXBUF)) == -1 ) { ERROR("ERROR: Unable to encrypt session key"); return 0; } n = 0; offset = 0; while (offset < ciphertext_len) { if ((n = Xsend(xssl->sockfd, &buf[offset], ciphertext_len-offset, 0)) < 0) { ERROR("ERROR sending pre-master secret"); return 0; } offset += n; } /* Init symmetric session ciphers with pre-master secret. Client encrypt context initialized with same key data as server decrypt context and vice versa. */ uint32_t salt[] = SALT; if (aes_init(pms, PRE_MASTER_SECRET_LENGTH/2, &pms[PRE_MASTER_SECRET_LENGTH/2], PRE_MASTER_SECRET_LENGTH/2, (unsigned char *)&salt, xssl->en, xssl->de)) { ERROR("ERROR initializing AES ciphers"); return 0; } free(pms); /* For now, omitting CLIENT DONE */ return 1; }
void cPacketStatWindow::sendBasic( NXWCLIENT ps, UI08 flag ) { if( ps == NULL ) return; //after error here this->flag = flag; Xsend( ps->toInt(), this->getBeginValid(), this->headerSize ); };
P_ITEM cTrade::tradestart(UOXSOCKET s, P_CHAR pc_i) { P_CHAR pc_currchar = currchar[s]; unsigned char msg[90]; P_ITEM pi_bps = Packitem(pc_currchar); P_ITEM pi_bpi = Packitem(pc_i); UOXSOCKET s2 = calcSocketFromChar(pc_i); if (pi_bps == NULL) //LB { sysmessage(s, "Time to buy a backpack!"); sysmessage(s2, "%s doesnt have a backpack!", pc_currchar->name.c_str()); return 0; } if (pi_bpi == NULL) { sysmessage(s2, "Time to buy a backpack!"); sysmessage(s, "%s doesnt have a backpack!", pc_i->name.c_str()); return 0; } P_ITEM pi_ps = Items->SpawnItem(s2, pc_currchar, 1, "#", 0, 0x1E, 0x5E, 0, 0, 0); if(pi_ps == NULL) return 0; pi_ps->pos = Coord_cl(26, 0, 0); pi_ps->SetContSerial(pc_currchar->serial); pi_ps->layer=0; pi_ps->type=1; pi_ps->dye=0; sendbpitem(s, pi_ps); if (s2 != INVALID_UOXSOCKET) sendbpitem(s2, pi_ps); P_ITEM pi_pi = Items->SpawnItem(s2,pc_i,1,"#",0,0x1E,0x5E,0,0,0); if (pi_pi == NULL) return 0; pi_pi->pos = Coord_cl(26, 0, 0); pi_pi->SetContSerial(pc_i->serial); pi_pi->layer=0; pi_pi->type=1; pi_pi->dye=0; sendbpitem(s, pi_pi); if (s2 != INVALID_UOXSOCKET) sendbpitem(s2, pi_pi); pi_pi->moreb1 = static_cast<unsigned char>((pi_ps->serial&0xFF000000)>>24); pi_pi->moreb2 = static_cast<unsigned char>((pi_ps->serial&0x00FF0000)>>16); pi_pi->moreb3 = static_cast<unsigned char>((pi_ps->serial&0x0000FF00)>>8); pi_pi->moreb4 = static_cast<unsigned char>((pi_ps->serial&0x000000FF)); pi_ps->more1 = static_cast<unsigned char>((pi_pi->serial&0xFF000000)>>24); pi_ps->more2 = static_cast<unsigned char>((pi_pi->serial&0x00FF0000)>>16); pi_ps->more3 = static_cast<unsigned char>((pi_pi->serial&0x0000FF00)>>8); pi_ps->more4 = static_cast<unsigned char>((pi_pi->serial&0x000000FF)); pi_ps->morez = 0; pi_pi->morez = 0; msg[0] = 0x6F; // Header Byte msg[1] = 0; // Size msg[2] = 47; // Size msg[3] = 0; // Initiate LongToCharPtr(pc_i->serial,msg+4); LongToCharPtr(pi_ps->serial,msg+8); LongToCharPtr(pi_pi->serial,msg+12); msg[16]=1; strcpy((char*)&(msg[17]), pc_i->name.c_str()); Xsend(s, msg, 47); if (s2 != INVALID_UOXSOCKET) { msg[0]=0x6F; // Header Byte msg[1]=0; // Size msg[2]=47; // Size msg[3]=0; // Initiate LongToCharPtr(pc_currchar->serial,msg+4); LongToCharPtr(pi_pi->serial,msg+8); LongToCharPtr(pi_ps->serial,msg+12); msg[16]=1; strcpy((char*)&(msg[17]), pc_currchar->name.c_str()); Xsend(s2, msg, 47); } return pi_ps; }
// guildstonemenu() : Opens the guild menu for a player // Recognizes Guildmaster with the owner fields of the stone. // Ofcourse checks for membership before opening any gump ;) void cGuildStone::Menu(UOXSOCKET s, int page) { //int total,i, counter,guild,recruit,war,member; int counter = 1; int lentext; int gumpnum = 0; char guildfealty[60],guildt[16],toggle[6]; static char mygump[MAXMEMRECWAR][257]; P_CHAR pc = currchar[s]; if (!isMember( pc ) && !pc->isGM()) { sysmessage(s, "You are not a member of this guild. Ask an existing guildmember to invite you into this guild."); return; } strcpy(guildfealty, "yourself"); if ((pc->guildfealty() != pc->serial)&&(pc->guildfealty() != INVALID_SERIAL)) { vector<SERIAL>::iterator it = find(member.begin(), member.end(), pc->guildfealty()); if ( it != member.end()) { strcpy(guildfealty, FindCharBySerial(*it)->name.c_str()); } } else pc->setGuildfealty( pc->serial ); if (this->ownserial == INVALID_SERIAL) CalcMaster(); P_CHAR guildmaster = FindCharBySerial(this->ownserial); switch (this->guildType) { case standard: strcpy(guildt, " Standard"); break; case order: strcpy(guildt, "n Order"); break; case chaos: strcpy(guildt, " Chaos"); break; } if (pc->guildtoggle()) strcpy(toggle, "On"); else strcpy(toggle, "Off"); // our prefix is 0xFE (darkstorm) gmprefix[7] = 0xFE; switch(page) { case 1: gumpnum=9; gmprefix[8] = 1; if (guildmaster<0) return; lentext = sprintf(mygump[0], "%s (%s %s)", this->guildName.c_str(), guildmaster->guildtitle().latin1(), guildmaster->name.c_str()); strcpy(mygump[1],"Recruit someone into the guild."); strcpy(mygump[2],"View the current roster."); strcpy(mygump[3],"View the guild's charter."); sprintf(mygump[4],"Declare your fealty. You are currently loyal to %s.",guildfealty); sprintf(mygump[5],"Toggle showing the guild's abbreviation in your name to unguilded people. Currently %s.",toggle); strcpy(mygump[6],"Resign from the guild."); strcpy(mygump[7],"View list of candidates who have been sponsored to the guild."); if ((pc->serial == this->ownserial)|| (pc->isGM())) // Guildmaster Access? { gumpnum=10; gmprefix[8] = 0; sprintf(mygump[8],"Access %s functions.", guildmaster->guildtitle().latin1()); sprintf(mygump[9],"View list of guild that %s has declared war on.", this->guildName.c_str()); sprintf(mygump[10],"View list of guilds that have declared war on %s.",this->guildName.c_str()); } else { // Normal Members access! sprintf(mygump[8],"View list of guilds that %s have declared war on.",this->guildName.c_str()); sprintf(mygump[9],"View list of guilds that have declared war on %s.",this->guildName.c_str()); } break; case 2: // guildmaster menu gumpnum=14; lentext = sprintf(mygump[0], "%s, %s functions", this->guildName.c_str(), guildmaster->guildtitle().latin1()); strcpy(mygump[1], "Set the guild name."); strcpy(mygump[2], "Set the guild's abbreviation."); sprintf(mygump[3], "Change the type of the guild. (Currently a%s guild.)",guildt); strcpy(mygump[4], "Set the guild's charter."); strcpy(mygump[5], "Dismiss a member."); strcpy(mygump[6], "Declare war from menu."); strcpy(mygump[7], "Declare war from targeting enemy."); strcpy(mygump[8], "Declare peace."); strcpy(mygump[9], "Accept a candidate seeking membership."); strcpy(mygump[10],"Refuse a candidate seeking membership."); strcpy(mygump[11],"Set the guildmaster's title."); strcpy(mygump[12],"Grant a title to another member."); strcpy(mygump[13],"Move this guildstone."); strcpy(mygump[14],"Return to the main menu."); gmprefix[8] = 2; break; case 3: // guild type gumpnum=4; lentext=sprintf(mygump[0], "Please select the type you want your guild to be related to."); strcpy(mygump[1], "Select this to return to main menu."); strcpy(mygump[2], "Set to Standard."); strcpy(mygump[3], "Set to Order."); strcpy(mygump[4], "Set to Chaos."); gmprefix[8] = 3; break; case 4: // edit charter gumpnum=3; lentext=sprintf(mygump[0], "Set %s charter.", this->guildName.c_str()); strcpy(mygump[1], "Select this to return to main menu."); strcpy(mygump[2], "Set the charter."); strcpy(mygump[3], "Set the webpage."); gmprefix[8] = 4; break; case 5: // view charter gumpnum=2; lentext=sprintf(mygump[0], "%s charter.", this->guildName.c_str()); sprintf(mygump[1], "%s. Select this to return to the main menu.", this->charter.c_str()); sprintf(mygump[2], "Visit the guild website at %s", this->webpage.c_str()); gmprefix[8] = 5; break; case 6: { // Candidates list gumpnum = this->recruit.size(); lentext=sprintf(mygump[0], "%s list of candidates.", this->guildName.c_str()); sprintf(mygump[1], "Select this to return to the menu."); unsigned int i; for (i = 0; i < recruit.size(); ++i) { strcpy(mygump[counter++], FindCharBySerial(this->recruit[i])->name.c_str()); } gmprefix[8] = 6; break; } case 7: { // roster gumpnum = this->member.size(); lentext=sprintf(mygump[0], "%s members roster.", this->guildName.c_str()); strcpy(mygump[1], "Select this to return to the menu."); counter=1; unsigned int i; for (i = 0; i < member.size(); ++i) { counter++; strcpy(mygump[counter], FindCharBySerial(this->member[i])->name.c_str()); } gmprefix[8] = 7; break; } case 8: { // member dismiss gumpnum = this->member.size(); lentext=sprintf(mygump[0], "Dismiss what member?"); strcpy(mygump[1], "Select this to return to the menu."); counter=1; unsigned int i; for ( i = 0; i < member.size(); ++i) { counter++; strcpy(mygump[counter], FindCharBySerial(this->member[i])->name.c_str()); } gmprefix[8] = 8; break; } case 9: { // Refuse Candidates gumpnum = this->recruit.size(); lentext=sprintf(mygump[0], "Refuse what candidate? %s", this->guildName.c_str()); strcpy(mygump[1], "Select this to return to the menu."); counter=1; unsigned int i; for ( i = 0; i < recruit.size(); ++i) { counter++; strcpy(mygump[counter], FindCharBySerial(this->recruit[i])->name.c_str()); } gmprefix[8] = 9; break; } case 10: // Accept Candidates { gumpnum = this->recruit.size(); lentext=sprintf(mygump[0], "Accept what candidate?.%s", this->guildName.c_str()); strcpy(mygump[1], "Select this to return to the menu."); counter=1; unsigned int i; for ( i = 0; i < recruit.size(); ++i) { counter++; strcpy(mygump[counter], FindCharBySerial(this->recruit[i])->name.c_str()); } gmprefix[8] = 10; break; } case 11: // War list { gumpnum = this->war.size(); lentext=sprintf(mygump[0], "Guild that %s has declared war on.", this->guildName.c_str()); strcpy(mygump[1], "Select this to return to the menu."); counter=1; unsigned int i; for ( i = 0; i < war.size(); ++i ) { counter++; cGuildStone* pStone = dynamic_cast<cGuildStone*>(FindItemBySerial(this->war[i])); strcpy(mygump[counter], pStone->guildName.c_str()); } gmprefix[8] = 11; break; } case 12: { // grant title gumpnum = this->member.size(); lentext=sprintf(mygump[0], "Grant a title to whom?"); strcpy(mygump[1], "Select this to return to the menu."); counter = 1; unsigned int i; for (i = 0; i < this->member.size(); ++i) { counter++; strcpy(mygump[counter], FindCharBySerial(this->member[i])->name.c_str()); } gmprefix[8] = 12; break; } case 13: { // fealty gumpnum = this->member.size(); lentext = sprintf(mygump[0], "Whom do you wish to be loyal to?"); strcpy(mygump[1], "Select this to return to the menu."); counter=1; unsigned int i; for (i = 0; i < this->member.size(); ++i) { counter++; strcpy(mygump[counter], FindCharBySerial(this->member[i])->name.c_str()); } gmprefix[8] = 13; break; } case 14: // declare War list { gumpnum=1; lentext=sprintf(mygump[0], "What guilds do you with to declare war?"); strcpy(mygump[1], "Select this to return to the menu."); counter=1; list<SERIAL>::iterator it; for (it = guilds.begin(); it != guilds.end(); ++it) { if ( !this->free && this->serial != *it ) { unsigned int i; for (i = 0; i < this->war.size(); ++i) { if (this->war[i] == *it) { ++gumpnum; P_ITEM pStone = FindItemBySerial(*it); strcpy(mygump[++counter], pStone->name().ascii()); } } } } gmprefix[8] = 14; break; } case 15: // declare peace list { gumpnum = this->war.size(); lentext = sprintf(mygump[0], "What guilds do you with to declare peace?"); strcpy(mygump[1], "Select this to return to the menu."); counter = 1; unsigned int i; for (i = 0; i < this->war.size(); ++i) { if ( this->war[i] != INVALID_SERIAL) { P_ITEM pStone = FindItemBySerial( this->war[i] ); strcpy(mygump[++counter], pStone->name().ascii()); } } gmprefix[8] = 15; break; } case 16: // War list 2 { gumpnum=1; lentext=sprintf(mygump[0], "Guilds that have decalred war on %s.", this->name().ascii()); strcpy(mygump[1], "Select this to return to the menu."); counter=1; list<SERIAL>::iterator it; for (it = guilds.begin(); it != guilds.end(); ++it) { if ((*it) != INVALID_SERIAL) { unsigned int i; for ( i = 0; i < this->war.size(); ++i) { if (this->war[i] == *it) { ++gumpnum; P_ITEM pStone = FindItemBySerial(*it); strcpy(mygump[++counter], pStone->name().ascii() ); } } } } gmprefix[8] = 16; break; } } int total=9+1+lentext+1; int i; for (i = 1; i <= gumpnum; i++) { total+=4+1+strlen(mygump[i]); } gmprefix[1] = total>>8; gmprefix[2] = total%256; LongToCharPtr(pc->serial, &gmprefix[3]); Xsend(s, gmprefix, 9); Xsend(s, &lentext, 1); Xsend(s, mygump[0], lentext); lentext = gumpnum; Xsend(s, &lentext, 1); for (i = 1; i <= gumpnum; i++) { gmmiddle[0]=0; gmmiddle[1]=0; Xsend(s,gmmiddle,4); lentext=strlen(mygump[i]); Xsend(s,&lentext,1); Xsend(s,mygump[i],lentext); } return; }
static void Sndbounce5(UOXSOCKET s) { bounce[1]=5; Xsend(s, bounce, 2); }
void cBoat::Turn(P_ITEM pBoat, int turn)//Turn the boat item, and send all the people/items on the boat to turnboatstuff() { if (pBoat == NULL) return; int id2 = pBoat->id2 ,olddir = pBoat->dir; unsigned short int Send[MAXCLIENT]; SERIAL serial; int a,dir, d=0; for (a = 0; a < now; ++a) { if (iteminrange(a, pBoat, BUILDRANGE) && perm[a]) { Send[d]=a; Xsend(a,wppause,2); d++; } } //Of course we need the boat items! serial = calcserial(pBoat->moreb1,pBoat->moreb2,pBoat->moreb3,pBoat->moreb4); if(serial == INVALID_SERIAL) return; P_ITEM pTiller = FindItemBySerial( serial ); if(pTiller == NULL) return; P_ITEM pi_p1 = FindItemBySerial( pBoat->morex ); if(pi_p1 == NULL) return; P_ITEM pi_p2 = FindItemBySerial( pBoat->morey ); if(pi_p2 == NULL) return; P_ITEM pi_hold = FindItemBySerial( pBoat->morez ); if(pi_hold == NULL) return; if(turn)//Right { pBoat->dir+=2; id2++; } else {//Left pBoat->dir-=2; id2--; } if(pBoat->dir>7) pBoat->dir-=4;//Make sure we dont have any DIR errors //if(pBoat->dir<0) pBoat->dir+=4; if(id2<pBoat->more1) id2+=4;//make sure we don't have any id errors either if(id2>pBoat->more2) id2-=4;//Now you know what the min/max id is for :-) pBoat->id2=id2;//set the id if(pBoat->id2==pBoat->more1) pBoat->dir=0;//extra DIR error checking if(pBoat->id2==pBoat->more2) pBoat->dir=6; if( Block( pBoat, 0, 0, pBoat->dir ) ) { pBoat->dir = olddir; for( a = 0; a < d; a++ ) { Xsend( Send[a], restart, 2 ); itemtalk( Send[a], pTiller, "Arr, something's in the way!" ); } return; } pBoat->id2=id2;//set the id if(pBoat->id2==pBoat->more1) pBoat->dir=0;//extra DIR error checking if(pBoat->id2==pBoat->more2) pBoat->dir=6; serial=pBoat->serial; // lb !!! unsigned int ci; vector<SERIAL> vecEntries = imultisp.getData(serial); for (ci = 0; ci < vecEntries.size(); ci++) { P_ITEM pi = FindItemBySerial(vecEntries[ci]); if (pi != NULL) TurnStuff(pBoat, pi, turn); } vecEntries.clear(); vecEntries = cmultisp.getData(serial); for (ci = 0; ci < vecEntries.size(); ci++) { P_CHAR pc = FindCharBySerial(vecEntries[ci]); if (pc != NULL) TurnStuff(pBoat, pc, turn); } //Set the DIR for use in the Offsets/IDs array dir = (pBoat->dir&0x0F)/2; //set it's Z to 0,0 inside the boat pi_p1->MoveTo(pBoat->pos.x,pBoat->pos.y,pi_p1->pos.z); pi_p1->id2 = cShipItems[dir][PORT_P_C];//change the ID pi_p2->MoveTo(pBoat->pos.x,pBoat->pos.y,pi_p2->pos.z); pi_p2->id2=cShipItems[dir][STAR_P_C]; pTiller->MoveTo(pBoat->pos.x,pBoat->pos.y, pTiller->pos.z); pTiller->id2=cShipItems[dir][TILLERID]; pi_hold->MoveTo(pBoat->pos.x,pBoat->pos.y, pi_hold->pos.z); pi_hold->id2=cShipItems[dir][HOLDID]; switch(pBoat->more1)//Now set what size boat it is and move the specail items { case 0x00: case 0x04: pi_p1->moveTo(pi_p1->pos + Coord_cl(iSmallShipOffsets[dir][PORT_PLANK][X], iSmallShipOffsets[dir][PORT_PLANK][Y], 0)); pi_p2->moveTo(pi_p2->pos + Coord_cl(iSmallShipOffsets[dir][STARB_PLANK][X], iSmallShipOffsets[dir][STARB_PLANK][Y], 0)); pTiller->moveTo(pTiller->pos + Coord_cl(iSmallShipOffsets[dir][TILLER][X], iSmallShipOffsets[dir][TILLER][Y], 0)); pi_hold->moveTo(pi_hold->pos + Coord_cl(iSmallShipOffsets[dir][HOLD][X], iSmallShipOffsets[dir][HOLD][Y], 0)); break; case 0x08: case 0x0C: pi_p1->moveTo(pi_p1->pos + Coord_cl(iMediumShipOffsets[dir][PORT_PLANK][X], iMediumShipOffsets[dir][PORT_PLANK][Y], 0) ); pi_p2->moveTo(pi_p2->pos + Coord_cl(iMediumShipOffsets[dir][STARB_PLANK][X], iMediumShipOffsets[dir][STARB_PLANK][Y], 0) ); pTiller->moveTo(pTiller->pos + Coord_cl(iMediumShipOffsets[dir][TILLER][X], iMediumShipOffsets[dir][TILLER][Y], 0) ); pi_hold->moveTo(pi_hold->pos + Coord_cl(iMediumShipOffsets[dir][HOLD][X], iMediumShipOffsets[dir][HOLD][Y], 0) ); break; case 0x10: case 0x14: pi_p1->moveTo(pi_p1->pos + Coord_cl(iLargeShipOffsets[dir][PORT_PLANK][X], iLargeShipOffsets[dir][PORT_PLANK][Y], 0) ); pi_p2->moveTo(pi_p2->pos + Coord_cl(iLargeShipOffsets[dir][STARB_PLANK][X], iLargeShipOffsets[dir][STARB_PLANK][Y], 0 ) ); pTiller->moveTo(pTiller->pos + Coord_cl(iLargeShipOffsets[dir][TILLER][X], iLargeShipOffsets[dir][TILLER][Y], 0 ) ); pi_hold->moveTo(pi_hold->pos + Coord_cl(iLargeShipOffsets[dir][HOLD][X], iLargeShipOffsets[dir][HOLD][Y], 0 ) ); break; default: { sprintf((char*)temp,"Turnboatstuff() more1 error! more1 = %c not found!\n",pBoat->more1); LogWarning((char*)temp); } } sendinrange(pi_p1); sendinrange(pi_p2); sendinrange(pi_hold); sendinrange(pTiller); for (a = 0; a < d; ++a) { Xsend(Send[a],restart,2); } }
/*! \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?")); }