1 /**
2 * @file msg.cpp
3 *
4 * Implementation of function for sending and reciving network messages.
5 */
6 #include "all.h"
7 #include "../3rdParty/Storm/Source/storm.h"
8 #include "../DiabloUI/diabloui.h"
9 #include "options.h"
10
11 DEVILUTION_BEGIN_NAMESPACE
12
13 static DWORD sgdwOwnerWait;
14 static DWORD sgdwRecvOffset;
15 static int sgnCurrMegaPlayer;
16 static DLevel sgLevels[NUMLEVELS];
17 static BYTE sbLastCmd;
18 static TMegaPkt *sgpCurrPkt;
19 static BYTE sgRecvBuf[sizeof(DLevel) + 1];
20 static BYTE sgbRecvCmd;
21 static LocalLevel sgLocals[NUMLEVELS];
22 static DJunk sgJunk;
23 static TMegaPkt *sgpMegaPkt;
24 static BOOLEAN sgbDeltaChanged;
25 static BYTE sgbDeltaChunks;
26 BOOL deltaload;
27 BYTE gbBufferMsgs;
28 int dwRecCount;
29
msg_get_next_packet()30 static void msg_get_next_packet()
31 {
32 TMegaPkt *result;
33
34 sgpCurrPkt = (TMegaPkt *)DiabloAllocPtr(sizeof(TMegaPkt));
35 sgpCurrPkt->pNext = NULL;
36 sgpCurrPkt->dwSpaceLeft = sizeof(result->data);
37
38 result = (TMegaPkt *)&sgpMegaPkt;
39 while (result->pNext)
40 result = result->pNext;
41
42 result->pNext = sgpCurrPkt;
43 }
44
msg_free_packets()45 static void msg_free_packets()
46 {
47 while (sgpMegaPkt) {
48 sgpCurrPkt = sgpMegaPkt->pNext;
49 MemFreeDbg(sgpMegaPkt);
50 sgpMegaPkt = sgpCurrPkt;
51 }
52 }
53
msg_pre_packet()54 static void msg_pre_packet()
55 {
56 int i;
57
58 i = -1;
59 for (TMegaPkt *pkt = sgpMegaPkt; pkt != NULL; pkt = pkt->pNext) {
60 BYTE *data = pkt->data;
61 int spaceLeft = sizeof(pkt->data);
62 while (spaceLeft != pkt->dwSpaceLeft) {
63 if (*data == FAKE_CMD_SETID) {
64 TFakeCmdPlr *cmd = (TFakeCmdPlr *)data;
65 data += sizeof(*cmd);
66 spaceLeft -= sizeof(*cmd);
67 i = cmd->bPlr;
68 } else if (*data == FAKE_CMD_DROPID) {
69 TFakeDropPlr *cmd = (TFakeDropPlr *)data;
70 data += sizeof(*cmd);
71 spaceLeft -= sizeof(*cmd);
72 multi_player_left(cmd->bPlr, cmd->dwReason);
73 } else {
74 int pktSize = ParseCmd(i, (TCmd *)data);
75 data += pktSize;
76 spaceLeft -= pktSize;
77 }
78 }
79 }
80 }
81
msg_send_packet(int pnum,const void * packet,DWORD dwSize)82 static void msg_send_packet(int pnum, const void *packet, DWORD dwSize)
83 {
84 TFakeCmdPlr cmd;
85
86 if (pnum != sgnCurrMegaPlayer) {
87 sgnCurrMegaPlayer = pnum;
88 cmd.bCmd = FAKE_CMD_SETID;
89 cmd.bPlr = pnum;
90 msg_send_packet(pnum, &cmd, sizeof(cmd));
91 }
92 if (sgpCurrPkt->dwSpaceLeft < dwSize)
93 msg_get_next_packet();
94
95 memcpy(sgpCurrPkt->data + sizeof(sgpCurrPkt->data) - sgpCurrPkt->dwSpaceLeft, packet, dwSize);
96 sgpCurrPkt->dwSpaceLeft -= dwSize;
97 }
98
msg_send_drop_pkt(int pnum,int reason)99 void msg_send_drop_pkt(int pnum, int reason)
100 {
101 TFakeDropPlr cmd;
102
103 cmd.dwReason = reason;
104 cmd.bCmd = FAKE_CMD_DROPID;
105 cmd.bPlr = pnum;
106 msg_send_packet(pnum, &cmd, sizeof(cmd));
107 }
108
msg_wait_for_turns()109 static int msg_wait_for_turns()
110 {
111 BOOL received;
112 DWORD turns;
113
114 if (sgbDeltaChunks == 0) {
115 nthread_send_and_recv_turn(0, 0);
116 if (!SNetGetOwnerTurnsWaiting(&turns) && SErrGetLastError() == STORM_ERROR_NOT_IN_GAME)
117 return 100;
118 if (SDL_GetTicks() - sgdwOwnerWait <= 2000 && turns < gdwTurnsInTransit)
119 return 0;
120 sgbDeltaChunks++;
121 }
122 multi_process_network_packets();
123 nthread_send_and_recv_turn(0, 0);
124 if (nthread_has_500ms_passed())
125 nthread_recv_turns(&received);
126
127 if (gbGameDestroyed)
128 return 100;
129 if (gbDeltaSender >= MAX_PLRS) {
130 sgbDeltaChunks = 0;
131 sgbRecvCmd = CMD_DLEVEL_END;
132 gbDeltaSender = myplr;
133 nthread_set_turn_upper_bit();
134 }
135 if (sgbDeltaChunks == MAX_CHUNKS - 1) {
136 sgbDeltaChunks = MAX_CHUNKS;
137 return 99;
138 }
139 return 100 * sgbDeltaChunks / MAX_CHUNKS;
140 }
141
msg_wait_resync()142 BOOL msg_wait_resync()
143 {
144 BOOL success;
145
146 msg_get_next_packet();
147 sgbDeltaChunks = 0;
148 sgnCurrMegaPlayer = -1;
149 sgbRecvCmd = CMD_DLEVEL_END;
150 gbBufferMsgs = 1;
151 sgdwOwnerWait = SDL_GetTicks();
152 success = UiProgressDialog("Waiting for game data...", 1, msg_wait_for_turns, 20);
153 gbBufferMsgs = 0;
154 if (!success) {
155 msg_free_packets();
156 return FALSE;
157 }
158
159 if (gbGameDestroyed) {
160 DrawDlg("The game ended");
161 msg_free_packets();
162 return FALSE;
163 }
164
165 if (sgbDeltaChunks != MAX_CHUNKS) {
166 DrawDlg("Unable to get level data");
167 msg_free_packets();
168 return FALSE;
169 }
170
171 return TRUE;
172 }
173
run_delta_info()174 void run_delta_info()
175 {
176 if (!gbIsMultiplayer)
177 return;
178
179 gbBufferMsgs = 2;
180 msg_pre_packet();
181 gbBufferMsgs = 0;
182 msg_free_packets();
183 }
184
DeltaExportItem(BYTE * dst,TCmdPItem * src)185 static BYTE *DeltaExportItem(BYTE *dst, TCmdPItem *src)
186 {
187 for (int i = 0; i < MAXITEMS; i++, src++) {
188 if (src->bCmd == 0xFF)
189 *dst++ = 0xFF;
190 else {
191 memcpy(dst, src, sizeof(TCmdPItem));
192 dst += sizeof(TCmdPItem);
193 }
194 }
195
196 return dst;
197 }
198
DeltaImportItem(BYTE * src,TCmdPItem * dst)199 static BYTE *DeltaImportItem(BYTE *src, TCmdPItem *dst)
200 {
201 for (int i = 0; i < MAXITEMS; i++, dst++) {
202 if (*src == 0xFF) {
203 memset(dst, 0xFF, sizeof(TCmdPItem));
204 src++;
205 } else {
206 memcpy(dst, src, sizeof(TCmdPItem));
207 src += sizeof(TCmdPItem);
208 }
209 }
210
211 return src;
212 }
213
DeltaExportObject(BYTE * dst,DObjectStr * src)214 static BYTE *DeltaExportObject(BYTE *dst, DObjectStr *src)
215 {
216 memcpy(dst, src, sizeof(DObjectStr) * MAXOBJECTS);
217 return dst + sizeof(DObjectStr) * MAXOBJECTS;
218 }
219
DeltaImportObject(BYTE * src,DObjectStr * dst)220 static BYTE *DeltaImportObject(BYTE *src, DObjectStr *dst)
221 {
222 memcpy(dst, src, sizeof(DObjectStr) * MAXOBJECTS);
223 return src + sizeof(DObjectStr) * MAXOBJECTS;
224 }
225
DeltaExportMonster(BYTE * dst,DMonsterStr * src)226 static BYTE *DeltaExportMonster(BYTE *dst, DMonsterStr *src)
227 {
228 for (int i = 0; i < MAXMONSTERS; i++, src++) {
229 if (src->_mx == 0xFF)
230 *dst++ = 0xFF;
231 else {
232 memcpy(dst, src, sizeof(DMonsterStr));
233 dst += sizeof(DMonsterStr);
234 }
235 }
236
237 return dst;
238 }
239
DeltaImportMonster(BYTE * src,DMonsterStr * dst)240 static BYTE *DeltaImportMonster(BYTE *src, DMonsterStr *dst)
241 {
242 for (int i = 0; i < MAXMONSTERS; i++, dst++) {
243 if (*src == 0xFF) {
244 memset(dst, 0xFF, sizeof(DMonsterStr));
245 src++;
246 } else {
247 memcpy(dst, src, sizeof(DMonsterStr));
248 src += sizeof(DMonsterStr);
249 }
250 }
251
252 return src;
253 }
254
DeltaExportJunk(BYTE * dst)255 static BYTE *DeltaExportJunk(BYTE *dst)
256 {
257 int i, q;
258
259 for (i = 0; i < MAXPORTAL; i++) {
260 if (sgJunk.portal[i].x == 0xFF) {
261 *dst++ = 0xFF;
262 } else {
263 memcpy(dst, &sgJunk.portal[i], sizeof(DPortal));
264 dst += sizeof(DPortal);
265 }
266 }
267
268 for (i = 0, q = 0; i < MAXQUESTS; i++) {
269 if (questlist[i]._qflags & QUEST_ANY) {
270 sgJunk.quests[q].qlog = quests[i]._qlog;
271 sgJunk.quests[q].qstate = quests[i]._qactive;
272 sgJunk.quests[q].qvar1 = quests[i]._qvar1;
273 memcpy(dst, &sgJunk.quests[q], sizeof(MultiQuests));
274 dst += sizeof(MultiQuests);
275 q++;
276 }
277 }
278
279 return dst;
280 }
281
DeltaImportJunk(BYTE * src)282 static void DeltaImportJunk(BYTE *src)
283 {
284 int i, q;
285
286 for (i = 0; i < MAXPORTAL; i++) {
287 if (*src == 0xFF) {
288 memset(&sgJunk.portal[i], 0xFF, sizeof(DPortal));
289 src++;
290 SetPortalStats(i, FALSE, 0, 0, 0, DTYPE_TOWN);
291 } else {
292 memcpy(&sgJunk.portal[i], src, sizeof(DPortal));
293 src += sizeof(DPortal);
294 SetPortalStats(
295 i,
296 TRUE,
297 sgJunk.portal[i].x,
298 sgJunk.portal[i].y,
299 sgJunk.portal[i].level,
300 (dungeon_type)sgJunk.portal[i].ltype);
301 }
302 }
303
304 for (i = 0, q = 0; i < MAXQUESTS; i++) {
305 if (questlist[i]._qflags & QUEST_ANY) {
306 memcpy(&sgJunk.quests[q], src, sizeof(MultiQuests));
307 src += sizeof(MultiQuests);
308 quests[i]._qlog = sgJunk.quests[q].qlog;
309 quests[i]._qactive = sgJunk.quests[q].qstate;
310 quests[i]._qvar1 = sgJunk.quests[q].qvar1;
311 q++;
312 }
313 }
314 }
315
msg_comp_level(BYTE * buffer,BYTE * end)316 static DWORD msg_comp_level(BYTE *buffer, BYTE *end)
317 {
318 DWORD size = end - buffer - 1;
319 DWORD pkSize = PkwareCompress(buffer + 1, size);
320
321 *buffer = size != pkSize;
322
323 return pkSize + 1;
324 }
325
DeltaExportData(int pnum)326 void DeltaExportData(int pnum)
327 {
328 if (sgbDeltaChanged) {
329 int size;
330 BYTE *dstEnd, *dst = (BYTE *)DiabloAllocPtr(sizeof(DLevel) + 1);
331 for (int i = 0; i < NUMLEVELS; i++) {
332 dstEnd = dst + 1;
333 dstEnd = DeltaExportItem(dstEnd, sgLevels[i].item);
334 dstEnd = DeltaExportObject(dstEnd, sgLevels[i].object);
335 dstEnd = DeltaExportMonster(dstEnd, sgLevels[i].monster);
336 size = msg_comp_level(dst, dstEnd);
337 dthread_send_delta(pnum, i + CMD_DLEVEL_0, dst, size);
338 }
339 dstEnd = dst + 1;
340 dstEnd = DeltaExportJunk(dstEnd);
341 size = msg_comp_level(dst, dstEnd);
342 dthread_send_delta(pnum, CMD_DLEVEL_JUNK, dst, size);
343 mem_free_dbg(dst);
344 }
345 char src = 0;
346 dthread_send_delta(pnum, CMD_DLEVEL_END, &src, 1);
347 }
348
DeltaImportData(BYTE cmd,DWORD recv_offset)349 static void DeltaImportData(BYTE cmd, DWORD recv_offset)
350 {
351 if (sgRecvBuf[0] != 0)
352 PkwareDecompress(&sgRecvBuf[1], recv_offset, sizeof(sgRecvBuf) - 1);
353
354 BYTE *src = &sgRecvBuf[1];
355 if (cmd == CMD_DLEVEL_JUNK) {
356 DeltaImportJunk(src);
357 } else if (cmd >= CMD_DLEVEL_0 && cmd <= CMD_DLEVEL_24) {
358 BYTE i = cmd - CMD_DLEVEL_0;
359 src = DeltaImportItem(src, sgLevels[i].item);
360 src = DeltaImportObject(src, sgLevels[i].object);
361 DeltaImportMonster(src, sgLevels[i].monster);
362 } else {
363 app_fatal("Unkown network message type: %d", cmd);
364 }
365
366 sgbDeltaChunks++;
367 sgbDeltaChanged = TRUE;
368 }
369
On_DLEVEL(int pnum,TCmd * pCmd)370 static DWORD On_DLEVEL(int pnum, TCmd *pCmd)
371 {
372 TCmdPlrInfoHdr *p = (TCmdPlrInfoHdr *)pCmd;
373
374 if (gbDeltaSender != pnum) {
375 if (p->bCmd == CMD_DLEVEL_END) {
376 gbDeltaSender = pnum;
377 sgbRecvCmd = CMD_DLEVEL_END;
378 } else if (p->bCmd == CMD_DLEVEL_0 && p->wOffset == 0) {
379 gbDeltaSender = pnum;
380 sgbRecvCmd = CMD_DLEVEL_END;
381 } else {
382 return p->wBytes + sizeof(*p);
383 }
384 }
385 if (sgbRecvCmd == CMD_DLEVEL_END) {
386 if (p->bCmd == CMD_DLEVEL_END) {
387 sgbDeltaChunks = MAX_CHUNKS - 1;
388 return p->wBytes + sizeof(*p);
389 } else if (p->bCmd == CMD_DLEVEL_0 && p->wOffset == 0) {
390 sgdwRecvOffset = 0;
391 sgbRecvCmd = p->bCmd;
392 } else {
393 return p->wBytes + sizeof(*p);
394 }
395 } else if (sgbRecvCmd != p->bCmd) {
396 DeltaImportData(sgbRecvCmd, sgdwRecvOffset);
397 if (p->bCmd == CMD_DLEVEL_END) {
398 sgbDeltaChunks = MAX_CHUNKS - 1;
399 sgbRecvCmd = CMD_DLEVEL_END;
400 return p->wBytes + sizeof(*p);
401 } else {
402 sgdwRecvOffset = 0;
403 sgbRecvCmd = p->bCmd;
404 }
405 }
406
407 /// ASSERT: assert(p->wOffset == sgdwRecvOffset);
408 memcpy(&sgRecvBuf[p->wOffset], &p[1], p->wBytes);
409 sgdwRecvOffset += p->wBytes;
410 return p->wBytes + sizeof(*p);
411 }
412
delta_init()413 void delta_init()
414 {
415 sgbDeltaChanged = FALSE;
416 memset(&sgJunk, 0xFF, sizeof(sgJunk));
417 memset(sgLevels, 0xFF, sizeof(sgLevels));
418 memset(sgLocals, 0, sizeof(sgLocals));
419 deltaload = FALSE;
420 }
421
delta_kill_monster(int mi,BYTE x,BYTE y,BYTE bLevel)422 void delta_kill_monster(int mi, BYTE x, BYTE y, BYTE bLevel)
423 {
424 if (!gbIsMultiplayer)
425 return;
426
427 sgbDeltaChanged = TRUE;
428 DMonsterStr *pD = &sgLevels[bLevel].monster[mi];
429 pD->_mx = x;
430 pD->_my = y;
431 pD->_mdir = monster[mi]._mdir;
432 pD->_mhitpoints = 0;
433 }
434
delta_monster_hp(int mi,int hp,BYTE bLevel)435 void delta_monster_hp(int mi, int hp, BYTE bLevel)
436 {
437 if (!gbIsMultiplayer)
438 return;
439
440 sgbDeltaChanged = TRUE;
441 DMonsterStr *pD = &sgLevels[bLevel].monster[mi];
442 if (pD->_mhitpoints > hp)
443 pD->_mhitpoints = hp;
444 }
445
delta_sync_monster(const TSyncMonster * pSync,BYTE bLevel)446 void delta_sync_monster(const TSyncMonster *pSync, BYTE bLevel)
447 {
448 if (!gbIsMultiplayer)
449 return;
450
451 /// ASSERT: assert(pSync != NULL);
452 /// ASSERT: assert(bLevel < NUMLEVELS);
453 sgbDeltaChanged = TRUE;
454
455 DMonsterStr *pD = &sgLevels[bLevel].monster[pSync->_mndx];
456 if (pD->_mhitpoints == 0)
457 return;
458
459 pD->_mx = pSync->_mx;
460 pD->_my = pSync->_my;
461 pD->_mactive = UCHAR_MAX;
462 pD->_menemy = pSync->_menemy;
463 }
464
delta_sync_golem(TCmdGolem * pG,int pnum,BYTE bLevel)465 void delta_sync_golem(TCmdGolem *pG, int pnum, BYTE bLevel)
466 {
467 if (!gbIsMultiplayer)
468 return;
469
470 sgbDeltaChanged = TRUE;
471 DMonsterStr *pD = &sgLevels[bLevel].monster[pnum];
472 pD->_mx = pG->_mx;
473 pD->_my = pG->_my;
474 pD->_mactive = UCHAR_MAX;
475 pD->_menemy = pG->_menemy;
476 pD->_mdir = pG->_mdir;
477 pD->_mhitpoints = pG->_mhitpoints;
478 }
479
delta_leave_sync(BYTE bLevel)480 void delta_leave_sync(BYTE bLevel)
481 {
482 if (!gbIsMultiplayer)
483 return;
484 if (currlevel == 0)
485 glSeedTbl[0] = AdvanceRndSeed();
486 if (currlevel <= 0)
487 return;
488
489 for (int i = 0; i < nummonsters; i++) {
490 int ma = monstactive[i];
491 if (monster[ma]._mhitpoints == 0)
492 continue;
493 sgbDeltaChanged = TRUE;
494 DMonsterStr *pD = &sgLevels[bLevel].monster[ma];
495 pD->_mx = monster[ma]._mx;
496 pD->_my = monster[ma]._my;
497 pD->_mdir = monster[ma]._mdir;
498 pD->_menemy = encode_enemy(ma);
499 pD->_mhitpoints = monster[ma]._mhitpoints;
500 pD->_mactive = monster[ma]._msquelch;
501 }
502 memcpy(&sgLocals[bLevel].automapsv, automapview, sizeof(automapview));
503 }
504
delta_sync_object(int oi,BYTE bCmd,BYTE bLevel)505 static void delta_sync_object(int oi, BYTE bCmd, BYTE bLevel)
506 {
507 if (!gbIsMultiplayer)
508 return;
509
510 sgbDeltaChanged = TRUE;
511 sgLevels[bLevel].object[oi].bCmd = bCmd;
512 }
513
delta_get_item(TCmdGItem * pI,BYTE bLevel)514 static BOOL delta_get_item(TCmdGItem *pI, BYTE bLevel)
515 {
516 int i;
517
518 if (!gbIsMultiplayer)
519 return TRUE;
520
521 TCmdPItem *pD = sgLevels[bLevel].item;
522 for (i = 0; i < MAXITEMS; i++, pD++) {
523 if (pD->bCmd == 0xFF || pD->wIndx != pI->wIndx || pD->wCI != pI->wCI || pD->dwSeed != pI->dwSeed)
524 continue;
525
526 if (pD->bCmd == CMD_WALKXY) {
527 return TRUE;
528 }
529 if (pD->bCmd == CMD_STAND) {
530 sgbDeltaChanged = TRUE;
531 pD->bCmd = CMD_WALKXY;
532 return TRUE;
533 }
534 if (pD->bCmd == CMD_ACK_PLRINFO) {
535 sgbDeltaChanged = TRUE;
536 pD->bCmd = 0xFF;
537 return TRUE;
538 }
539
540 app_fatal("delta:1");
541 }
542
543 if ((pI->wCI & CF_PREGEN) == 0)
544 return FALSE;
545
546 pD = sgLevels[bLevel].item;
547 for (i = 0; i < MAXITEMS; i++, pD++) {
548 if (pD->bCmd == 0xFF) {
549 sgbDeltaChanged = TRUE;
550 pD->bCmd = CMD_WALKXY;
551 pD->x = pI->x;
552 pD->y = pI->y;
553 pD->wIndx = pI->wIndx;
554 pD->wCI = pI->wCI;
555 pD->dwSeed = pI->dwSeed;
556 pD->bId = pI->bId;
557 pD->bDur = pI->bDur;
558 pD->bMDur = pI->bMDur;
559 pD->bCh = pI->bCh;
560 pD->bMCh = pI->bMCh;
561 pD->wValue = pI->wValue;
562 pD->dwBuff = pI->dwBuff;
563 pD->wToHit = pI->wToHit;
564 pD->wMaxDam = pI->wMaxDam;
565 pD->bMinStr = pI->bMinStr;
566 pD->bMinMag = pI->bMinMag;
567 pD->bMinDex = pI->bMinDex;
568 pD->bAC = pI->bAC;
569 break;
570 }
571 }
572 return TRUE;
573 }
574
delta_put_item(TCmdPItem * pI,int x,int y,BYTE bLevel)575 static void delta_put_item(TCmdPItem *pI, int x, int y, BYTE bLevel)
576 {
577 int i;
578
579 if (!gbIsMultiplayer)
580 return;
581
582 TCmdPItem *pD = sgLevels[bLevel].item;
583 for (i = 0; i < MAXITEMS; i++, pD++) {
584 if (pD->bCmd != CMD_WALKXY
585 && pD->bCmd != 0xFF
586 && pD->wIndx == pI->wIndx
587 && pD->wCI == pI->wCI
588 && pD->dwSeed == pI->dwSeed) {
589 if (pD->bCmd == CMD_ACK_PLRINFO)
590 return;
591 app_fatal("Trying to drop a floor item?");
592 }
593 }
594
595 pD = sgLevels[bLevel].item;
596 for (i = 0; i < MAXITEMS; i++, pD++) {
597 if (pD->bCmd == 0xFF) {
598 sgbDeltaChanged = TRUE;
599 memcpy(pD, pI, sizeof(TCmdPItem));
600 pD->bCmd = CMD_ACK_PLRINFO;
601 pD->x = x;
602 pD->y = y;
603 return;
604 }
605 }
606 }
607
delta_portal_inited(int i)608 BOOL delta_portal_inited(int i)
609 {
610 return sgJunk.portal[i].x == 0xFF;
611 }
612
delta_quest_inited(int i)613 BOOL delta_quest_inited(int i)
614 {
615 return sgJunk.quests[i].qstate != 0xFF;
616 }
617
DeltaAddItem(int ii)618 void DeltaAddItem(int ii)
619 {
620 int i;
621
622 if (!gbIsMultiplayer)
623 return;
624
625 TCmdPItem *pD = sgLevels[currlevel].item;
626 for (i = 0; i < MAXITEMS; i++, pD++) {
627 if (pD->bCmd != 0xFF
628 && pD->wIndx == item[ii].IDidx
629 && pD->wCI == item[ii]._iCreateInfo
630 && pD->dwSeed == item[ii]._iSeed
631 && (pD->bCmd == CMD_WALKXY || pD->bCmd == CMD_STAND)) {
632 return;
633 }
634 }
635
636 pD = sgLevels[currlevel].item;
637 for (i = 0; i < MAXITEMS; i++, pD++) {
638 if (pD->bCmd == 0xFF) {
639 sgbDeltaChanged = TRUE;
640 pD->bCmd = CMD_STAND;
641 pD->x = item[ii]._ix;
642 pD->y = item[ii]._iy;
643 pD->wIndx = item[ii].IDidx;
644 pD->wCI = item[ii]._iCreateInfo;
645 pD->dwSeed = item[ii]._iSeed;
646 pD->bId = item[ii]._iIdentified;
647 pD->bDur = item[ii]._iDurability;
648 pD->bMDur = item[ii]._iMaxDur;
649 pD->bCh = item[ii]._iCharges;
650 pD->bMCh = item[ii]._iMaxCharges;
651 pD->wValue = item[ii]._ivalue;
652 pD->wToHit = item[ii]._iPLToHit;
653 pD->wMaxDam = item[ii]._iMaxDam;
654 pD->bMinStr = item[ii]._iMinStr;
655 pD->bMinMag = item[ii]._iMinMag;
656 pD->bMinDex = item[ii]._iMinDex;
657 pD->bAC = item[ii]._iAC;
658 pD->dwBuff = item[ii].dwBuff;
659 return;
660 }
661 }
662 }
663
DeltaSaveLevel()664 void DeltaSaveLevel()
665 {
666 if (!gbIsMultiplayer)
667 return;
668
669 for (int i = 0; i < MAX_PLRS; i++) {
670 if (i != myplr)
671 plr[i]._pGFXLoad = 0;
672 }
673 plr[myplr]._pLvlVisited[currlevel] = TRUE;
674 delta_leave_sync(currlevel);
675 }
676
DeltaLoadLevel()677 void DeltaLoadLevel()
678 {
679 int ot;
680 int i, j, k, l;
681 int x, y, xx, yy;
682 BOOL done;
683
684 if (!gbIsMultiplayer)
685 return;
686
687 deltaload = TRUE;
688 if (currlevel != 0) {
689 for (i = 0; i < nummonsters; i++) {
690 if (sgLevels[currlevel].monster[i]._mx != 0xFF) {
691 M_ClearSquares(i);
692 x = sgLevels[currlevel].monster[i]._mx;
693 y = sgLevels[currlevel].monster[i]._my;
694 monster[i]._mx = x;
695 monster[i]._my = y;
696 monster[i]._moldx = x;
697 monster[i]._moldy = y;
698 monster[i]._mfutx = x;
699 monster[i]._mfuty = y;
700 if (sgLevels[currlevel].monster[i]._mhitpoints != -1)
701 monster[i]._mhitpoints = sgLevels[currlevel].monster[i]._mhitpoints;
702 if (sgLevels[currlevel].monster[i]._mhitpoints == 0) {
703 monster[i]._moldx = sgLevels[currlevel].monster[i]._mx; // CODEFIX: useless assignment
704 monster[i]._moldy = sgLevels[currlevel].monster[i]._my; // CODEFIX: useless assignment
705 M_ClearSquares(i);
706 if (monster[i]._mAi != AI_DIABLO) {
707 if (monster[i]._uniqtype == 0)
708 /// ASSERT: assert(monster[i].MType != NULL);
709 AddDead(monster[i]._mx, monster[i]._my, monster[i].MType->mdeadval, (direction)monster[i]._mdir);
710 else
711 AddDead(monster[i]._mx, monster[i]._my, monster[i]._udeadval, (direction)monster[i]._mdir);
712 }
713 monster[i]._mDelFlag = TRUE;
714 M_UpdateLeader(i);
715 } else {
716 decode_enemy(i, sgLevels[currlevel].monster[i]._menemy);
717 if ((monster[i]._mx && monster[i]._mx != 1) || monster[i]._my)
718 dMonster[monster[i]._mx][monster[i]._my] = i + 1;
719 if (i < MAX_PLRS) {
720 MAI_Golum(i);
721 monster[i]._mFlags |= (MFLAG_TARGETS_MONSTER | MFLAG_GOLEM);
722 } else {
723 M_StartStand(i, monster[i]._mdir);
724 }
725 monster[i]._msquelch = sgLevels[currlevel].monster[i]._mactive;
726 }
727 }
728 }
729 memcpy(automapview, &sgLocals[currlevel], sizeof(automapview));
730 }
731
732 for (i = 0; i < MAXITEMS; i++) {
733 if (sgLevels[currlevel].item[i].bCmd != 0xFF) {
734 if (sgLevels[currlevel].item[i].bCmd == CMD_WALKXY) {
735 int ii = FindGetItem(
736 sgLevels[currlevel].item[i].wIndx,
737 sgLevels[currlevel].item[i].wCI,
738 sgLevels[currlevel].item[i].dwSeed);
739 if (ii != -1) {
740 if (dItem[item[ii]._ix][item[ii]._iy] == ii + 1)
741 dItem[item[ii]._ix][item[ii]._iy] = 0;
742 DeleteItem(ii, i);
743 }
744 }
745 if (sgLevels[currlevel].item[i].bCmd == CMD_ACK_PLRINFO) {
746 int ii = AllocateItem();
747
748 if (sgLevels[currlevel].item[i].wIndx == IDI_EAR) {
749 RecreateEar(
750 ii,
751 sgLevels[currlevel].item[i].wCI,
752 sgLevels[currlevel].item[i].dwSeed,
753 sgLevels[currlevel].item[i].bId,
754 sgLevels[currlevel].item[i].bDur,
755 sgLevels[currlevel].item[i].bMDur,
756 sgLevels[currlevel].item[i].bCh,
757 sgLevels[currlevel].item[i].bMCh,
758 sgLevels[currlevel].item[i].wValue,
759 sgLevels[currlevel].item[i].dwBuff);
760 } else {
761 RecreateItem(
762 ii,
763 sgLevels[currlevel].item[i].wIndx,
764 sgLevels[currlevel].item[i].wCI,
765 sgLevels[currlevel].item[i].dwSeed,
766 sgLevels[currlevel].item[i].wValue,
767 (sgLevels[currlevel].item[i].dwBuff & CF_HELLFIRE) != 0);
768 if (sgLevels[currlevel].item[i].bId)
769 item[ii]._iIdentified = TRUE;
770 item[ii]._iDurability = sgLevels[currlevel].item[i].bDur;
771 item[ii]._iMaxDur = sgLevels[currlevel].item[i].bMDur;
772 item[ii]._iCharges = sgLevels[currlevel].item[i].bCh;
773 item[ii]._iMaxCharges = sgLevels[currlevel].item[i].bMCh;
774 item[ii]._iPLToHit = sgLevels[currlevel].item[i].wToHit;
775 item[ii]._iMaxDam = sgLevels[currlevel].item[i].wMaxDam;
776 item[ii]._iMinStr = sgLevels[currlevel].item[i].bMinStr;
777 item[ii]._iMinMag = sgLevels[currlevel].item[i].bMinMag;
778 item[ii]._iMinDex = sgLevels[currlevel].item[i].bMinDex;
779 item[ii]._iAC = sgLevels[currlevel].item[i].bAC;
780 item[ii].dwBuff = sgLevels[currlevel].item[i].dwBuff;
781 }
782 x = sgLevels[currlevel].item[i].x;
783 y = sgLevels[currlevel].item[i].y;
784 if (!CanPut(x, y)) {
785 done = FALSE;
786 for (k = 1; k < 50 && !done; k++) {
787 for (j = -k; j <= k && !done; j++) {
788 yy = y + j;
789 for (l = -k; l <= k && !done; l++) {
790 xx = x + l;
791 if (CanPut(xx, yy)) {
792 done = TRUE;
793 x = xx;
794 y = yy;
795 }
796 }
797 }
798 }
799 }
800 item[ii]._ix = x;
801 item[ii]._iy = y;
802 dItem[item[ii]._ix][item[ii]._iy] = ii + 1;
803 RespawnItem(ii, FALSE);
804 }
805 }
806 }
807
808 if (currlevel != 0) {
809 for (i = 0; i < MAXOBJECTS; i++) {
810 switch (sgLevels[currlevel].object[i].bCmd) {
811 case CMD_OPENDOOR:
812 case CMD_CLOSEDOOR:
813 case CMD_OPERATEOBJ:
814 case CMD_PLROPOBJ:
815 SyncOpObject(-1, sgLevels[currlevel].object[i].bCmd, i);
816 break;
817 case CMD_BREAKOBJ:
818 SyncBreakObj(-1, i);
819 break;
820 }
821 }
822
823 for (i = 0; i < nobjects; i++) {
824 ot = object[objectactive[i]]._otype;
825 if (ot == OBJ_TRAPL || ot == OBJ_TRAPR)
826 Obj_Trap(objectactive[i]);
827 }
828 }
829 deltaload = FALSE;
830 }
831
NetSendCmd(BOOL bHiPri,BYTE bCmd)832 void NetSendCmd(BOOL bHiPri, BYTE bCmd)
833 {
834 TCmd cmd;
835
836 cmd.bCmd = bCmd;
837 if (bHiPri)
838 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
839 else
840 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
841 }
842
NetSendCmdGolem(BYTE mx,BYTE my,BYTE dir,BYTE menemy,int hp,BYTE cl)843 void NetSendCmdGolem(BYTE mx, BYTE my, BYTE dir, BYTE menemy, int hp, BYTE cl)
844 {
845 TCmdGolem cmd;
846
847 cmd.bCmd = CMD_AWAKEGOLEM;
848 cmd._mx = mx;
849 cmd._my = my;
850 cmd._mdir = dir;
851 cmd._menemy = menemy;
852 cmd._mhitpoints = hp;
853 cmd._currlevel = cl;
854 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
855 }
856
NetSendCmdLoc(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y)857 void NetSendCmdLoc(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y)
858 {
859 ALIGN_BY_1 TCmdLoc cmd;
860
861 cmd.bCmd = bCmd;
862 cmd.x = x;
863 cmd.y = y;
864 if (bHiPri)
865 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
866 else
867 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
868 }
869
NetSendCmdLocParam1(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1)870 void NetSendCmdLocParam1(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y, WORD wParam1)
871 {
872 TCmdLocParam1 cmd;
873
874 cmd.bCmd = bCmd;
875 cmd.x = x;
876 cmd.y = y;
877 cmd.wParam1 = wParam1;
878 if (bHiPri)
879 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
880 else
881 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
882 }
883
NetSendCmdLocParam2(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1,WORD wParam2)884 void NetSendCmdLocParam2(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y, WORD wParam1, WORD wParam2)
885 {
886 TCmdLocParam2 cmd;
887
888 cmd.bCmd = bCmd;
889 cmd.x = x;
890 cmd.y = y;
891 cmd.wParam1 = wParam1;
892 cmd.wParam2 = wParam2;
893 if (bHiPri)
894 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
895 else
896 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
897 }
898
NetSendCmdLocParam3(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y,WORD wParam1,WORD wParam2,WORD wParam3)899 void NetSendCmdLocParam3(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y, WORD wParam1, WORD wParam2, WORD wParam3)
900 {
901 TCmdLocParam3 cmd;
902
903 cmd.bCmd = bCmd;
904 cmd.x = x;
905 cmd.y = y;
906 cmd.wParam1 = wParam1;
907 cmd.wParam2 = wParam2;
908 cmd.wParam3 = wParam3;
909 if (bHiPri)
910 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
911 else
912 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
913 }
914
NetSendCmdParam1(BOOL bHiPri,BYTE bCmd,WORD wParam1)915 void NetSendCmdParam1(BOOL bHiPri, BYTE bCmd, WORD wParam1)
916 {
917 ALIGN_BY_1 TCmdParam1 cmd;
918
919 cmd.bCmd = bCmd;
920 cmd.wParam1 = wParam1;
921 if (bHiPri)
922 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
923 else
924 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
925 }
926
NetSendCmdParam2(BOOL bHiPri,BYTE bCmd,WORD wParam1,WORD wParam2)927 void NetSendCmdParam2(BOOL bHiPri, BYTE bCmd, WORD wParam1, WORD wParam2)
928 {
929 TCmdParam2 cmd;
930
931 cmd.bCmd = bCmd;
932 cmd.wParam1 = wParam1;
933 cmd.wParam2 = wParam2;
934 if (bHiPri)
935 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
936 else
937 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
938 }
939
NetSendCmdParam3(BOOL bHiPri,BYTE bCmd,WORD wParam1,WORD wParam2,WORD wParam3)940 void NetSendCmdParam3(BOOL bHiPri, BYTE bCmd, WORD wParam1, WORD wParam2, WORD wParam3)
941 {
942 TCmdParam3 cmd;
943
944 cmd.bCmd = bCmd;
945 cmd.wParam1 = wParam1;
946 cmd.wParam2 = wParam2;
947 cmd.wParam3 = wParam3;
948 if (bHiPri)
949 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
950 else
951 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
952 }
953
NetSendCmdQuest(BOOL bHiPri,BYTE q)954 void NetSendCmdQuest(BOOL bHiPri, BYTE q)
955 {
956 TCmdQuest cmd;
957
958 cmd.q = q;
959 cmd.bCmd = CMD_SYNCQUEST;
960 cmd.qstate = quests[q]._qactive;
961 cmd.qlog = quests[q]._qlog;
962 cmd.qvar1 = quests[q]._qvar1;
963 if (bHiPri)
964 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
965 else
966 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
967 }
968
NetSendCmdGItem(BOOL bHiPri,BYTE bCmd,BYTE mast,BYTE pnum,BYTE ii)969 void NetSendCmdGItem(BOOL bHiPri, BYTE bCmd, BYTE mast, BYTE pnum, BYTE ii)
970 {
971 TCmdGItem cmd;
972
973 cmd.bCmd = bCmd;
974 cmd.bPnum = pnum;
975 cmd.bMaster = mast;
976 cmd.bLevel = currlevel;
977 cmd.bCursitem = ii;
978 cmd.dwTime = 0;
979 cmd.x = item[ii]._ix;
980 cmd.y = item[ii]._iy;
981 cmd.wIndx = item[ii].IDidx;
982
983 if (item[ii].IDidx == IDI_EAR) {
984 cmd.wCI = item[ii]._iName[8] | (item[ii]._iName[7] << 8);
985 cmd.dwSeed = item[ii]._iName[12] | ((item[ii]._iName[11] | ((item[ii]._iName[10] | (item[ii]._iName[9] << 8)) << 8)) << 8);
986 cmd.bId = item[ii]._iName[13];
987 cmd.bDur = item[ii]._iName[14];
988 cmd.bMDur = item[ii]._iName[15];
989 cmd.bCh = item[ii]._iName[16];
990 cmd.bMCh = item[ii]._iName[17];
991 cmd.wValue = item[ii]._ivalue | (item[ii]._iName[18] << 8) | ((item[ii]._iCurs - ICURS_EAR_SORCERER) << 6);
992 cmd.dwBuff = item[ii]._iName[22] | ((item[ii]._iName[21] | ((item[ii]._iName[20] | (item[ii]._iName[19] << 8)) << 8)) << 8);
993 } else {
994 cmd.wCI = item[ii]._iCreateInfo;
995 cmd.dwSeed = item[ii]._iSeed;
996 cmd.bId = item[ii]._iIdentified;
997 cmd.bDur = item[ii]._iDurability;
998 cmd.bMDur = item[ii]._iMaxDur;
999 cmd.bCh = item[ii]._iCharges;
1000 cmd.bMCh = item[ii]._iMaxCharges;
1001 cmd.wValue = item[ii]._ivalue;
1002 cmd.wToHit = item[ii]._iPLToHit;
1003 cmd.wMaxDam = item[ii]._iMaxDam;
1004 cmd.bMinStr = item[ii]._iMinStr;
1005 cmd.bMinMag = item[ii]._iMinMag;
1006 cmd.bMinDex = item[ii]._iMinDex;
1007 cmd.bAC = item[ii]._iAC;
1008 cmd.dwBuff = item[ii].dwBuff;
1009 }
1010
1011 if (bHiPri)
1012 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1013 else
1014 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1015 }
1016
NetSendCmdGItem2(BOOL usonly,BYTE bCmd,BYTE mast,BYTE pnum,TCmdGItem * p)1017 void NetSendCmdGItem2(BOOL usonly, BYTE bCmd, BYTE mast, BYTE pnum, TCmdGItem *p)
1018 {
1019 TCmdGItem cmd;
1020
1021 memcpy(&cmd, p, sizeof(cmd));
1022 cmd.bPnum = pnum;
1023 cmd.bCmd = bCmd;
1024 cmd.bMaster = mast;
1025
1026 if (!usonly) {
1027 cmd.dwTime = 0;
1028 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1029 return;
1030 }
1031
1032 int ticks = SDL_GetTicks();
1033 if (cmd.dwTime == 0) {
1034 cmd.dwTime = ticks;
1035 } else if (ticks - cmd.dwTime > 5000) {
1036 return;
1037 }
1038
1039 multi_msg_add((BYTE *)&cmd.bCmd, sizeof(cmd));
1040 }
1041
NetSendCmdReq2(BYTE bCmd,BYTE mast,BYTE pnum,TCmdGItem * p)1042 BOOL NetSendCmdReq2(BYTE bCmd, BYTE mast, BYTE pnum, TCmdGItem *p)
1043 {
1044 TCmdGItem cmd;
1045
1046 memcpy(&cmd, p, sizeof(cmd));
1047 cmd.bCmd = bCmd;
1048 cmd.bPnum = pnum;
1049 cmd.bMaster = mast;
1050
1051 int ticks = SDL_GetTicks();
1052 if (cmd.dwTime == 0)
1053 cmd.dwTime = ticks;
1054 else if (ticks - cmd.dwTime > 5000)
1055 return FALSE;
1056
1057 multi_msg_add((BYTE *)&cmd.bCmd, sizeof(cmd));
1058
1059 return TRUE;
1060 }
1061
NetSendCmdExtra(TCmdGItem * p)1062 void NetSendCmdExtra(TCmdGItem *p)
1063 {
1064 TCmdGItem cmd;
1065
1066 memcpy(&cmd, p, sizeof(cmd));
1067 cmd.dwTime = 0;
1068 cmd.bCmd = CMD_ITEMEXTRA;
1069 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1070 }
1071
NetSendCmdPItem(BOOL bHiPri,BYTE bCmd,BYTE x,BYTE y)1072 void NetSendCmdPItem(BOOL bHiPri, BYTE bCmd, BYTE x, BYTE y)
1073 {
1074 TCmdPItem cmd;
1075
1076 cmd.bCmd = bCmd;
1077 cmd.x = x;
1078 cmd.y = y;
1079 cmd.wIndx = plr[myplr].HoldItem.IDidx;
1080
1081 if (plr[myplr].HoldItem.IDidx == IDI_EAR) {
1082 cmd.wCI = plr[myplr].HoldItem._iName[8] | (plr[myplr].HoldItem._iName[7] << 8);
1083 cmd.dwSeed = plr[myplr].HoldItem._iName[12] | ((plr[myplr].HoldItem._iName[11] | ((plr[myplr].HoldItem._iName[10] | (plr[myplr].HoldItem._iName[9] << 8)) << 8)) << 8);
1084 cmd.bId = plr[myplr].HoldItem._iName[13];
1085 cmd.bDur = plr[myplr].HoldItem._iName[14];
1086 cmd.bMDur = plr[myplr].HoldItem._iName[15];
1087 cmd.bCh = plr[myplr].HoldItem._iName[16];
1088 cmd.bMCh = plr[myplr].HoldItem._iName[17];
1089 cmd.wValue = plr[myplr].HoldItem._ivalue | (plr[myplr].HoldItem._iName[18] << 8) | ((plr[myplr].HoldItem._iCurs - ICURS_EAR_SORCERER) << 6);
1090 cmd.dwBuff = plr[myplr].HoldItem._iName[22] | ((plr[myplr].HoldItem._iName[21] | ((plr[myplr].HoldItem._iName[20] | (plr[myplr].HoldItem._iName[19] << 8)) << 8)) << 8);
1091 } else {
1092 cmd.wCI = plr[myplr].HoldItem._iCreateInfo;
1093 cmd.dwSeed = plr[myplr].HoldItem._iSeed;
1094 cmd.bId = plr[myplr].HoldItem._iIdentified;
1095 cmd.bDur = plr[myplr].HoldItem._iDurability;
1096 cmd.bMDur = plr[myplr].HoldItem._iMaxDur;
1097 cmd.bCh = plr[myplr].HoldItem._iCharges;
1098 cmd.bMCh = plr[myplr].HoldItem._iMaxCharges;
1099 cmd.wValue = plr[myplr].HoldItem._ivalue;
1100 cmd.wToHit = plr[myplr].HoldItem._iPLToHit;
1101 cmd.wMaxDam = plr[myplr].HoldItem._iMaxDam;
1102 cmd.bMinStr = plr[myplr].HoldItem._iMinStr;
1103 cmd.bMinMag = plr[myplr].HoldItem._iMinMag;
1104 cmd.bMinDex = plr[myplr].HoldItem._iMinDex;
1105 cmd.bAC = plr[myplr].HoldItem._iAC;
1106 cmd.dwBuff = plr[myplr].HoldItem.dwBuff;
1107 }
1108
1109 if (bHiPri)
1110 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1111 else
1112 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1113 }
1114
NetSendCmdChItem(BOOL bHiPri,BYTE bLoc)1115 void NetSendCmdChItem(BOOL bHiPri, BYTE bLoc)
1116 {
1117 TCmdChItem cmd;
1118
1119 cmd.bCmd = CMD_CHANGEPLRITEMS;
1120 cmd.bLoc = bLoc;
1121 cmd.wIndx = plr[myplr].HoldItem.IDidx;
1122 cmd.wCI = plr[myplr].HoldItem._iCreateInfo;
1123 cmd.dwSeed = plr[myplr].HoldItem._iSeed;
1124 cmd.bId = plr[myplr].HoldItem._iIdentified;
1125 cmd.dwBuff = plr[myplr].HoldItem.dwBuff;
1126
1127 if (bHiPri)
1128 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1129 else
1130 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1131 }
1132
NetSendCmdDelItem(BOOL bHiPri,BYTE bLoc)1133 void NetSendCmdDelItem(BOOL bHiPri, BYTE bLoc)
1134 {
1135 TCmdDelItem cmd;
1136
1137 cmd.bLoc = bLoc;
1138 cmd.bCmd = CMD_DELPLRITEMS;
1139 if (bHiPri)
1140 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1141 else
1142 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1143 }
1144
NetSendCmdDItem(BOOL bHiPri,int ii)1145 void NetSendCmdDItem(BOOL bHiPri, int ii)
1146 {
1147 TCmdPItem cmd;
1148
1149 cmd.bCmd = CMD_DROPITEM;
1150 cmd.x = item[ii]._ix;
1151 cmd.y = item[ii]._iy;
1152 cmd.wIndx = item[ii].IDidx;
1153
1154 if (item[ii].IDidx == IDI_EAR) {
1155 cmd.wCI = item[ii]._iName[8] | (item[ii]._iName[7] << 8);
1156 cmd.dwSeed = item[ii]._iName[12] | ((item[ii]._iName[11] | ((item[ii]._iName[10] | (item[ii]._iName[9] << 8)) << 8)) << 8);
1157 cmd.bId = item[ii]._iName[13];
1158 cmd.bDur = item[ii]._iName[14];
1159 cmd.bMDur = item[ii]._iName[15];
1160 cmd.bCh = item[ii]._iName[16];
1161 cmd.bMCh = item[ii]._iName[17];
1162 cmd.wValue = item[ii]._ivalue | (item[ii]._iName[18] << 8) | ((item[ii]._iCurs - ICURS_EAR_SORCERER) << 6);
1163 cmd.dwBuff = item[ii]._iName[22] | ((item[ii]._iName[21] | ((item[ii]._iName[20] | (item[ii]._iName[19] << 8)) << 8)) << 8);
1164 } else {
1165 cmd.wCI = item[ii]._iCreateInfo;
1166 cmd.dwSeed = item[ii]._iSeed;
1167 cmd.bId = item[ii]._iIdentified;
1168 cmd.bDur = item[ii]._iDurability;
1169 cmd.bMDur = item[ii]._iMaxDur;
1170 cmd.bCh = item[ii]._iCharges;
1171 cmd.bMCh = item[ii]._iMaxCharges;
1172 cmd.wValue = item[ii]._ivalue;
1173 cmd.wToHit = item[ii]._iPLToHit;
1174 cmd.wMaxDam = item[ii]._iMaxDam;
1175 cmd.bMinStr = item[ii]._iMinStr;
1176 cmd.bMinMag = item[ii]._iMinMag;
1177 cmd.bMinDex = item[ii]._iMinDex;
1178 cmd.bAC = item[ii]._iAC;
1179 cmd.dwBuff = item[ii].dwBuff;
1180 }
1181
1182 if (bHiPri)
1183 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1184 else
1185 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1186 }
1187
i_own_level(int nReqLevel)1188 static BOOL i_own_level(int nReqLevel)
1189 {
1190 int i;
1191
1192 for (i = 0; i < MAX_PLRS; i++) {
1193 if (!plr[i].plractive)
1194 continue;
1195 if (plr[i]._pLvlChanging)
1196 continue;
1197 if (plr[i].plrlevel != nReqLevel)
1198 continue;
1199 if (i == myplr && gbBufferMsgs != 0)
1200 continue;
1201 break;
1202 }
1203 return i == myplr;
1204 }
1205
NetSendCmdDamage(BOOL bHiPri,BYTE bPlr,DWORD dwDam)1206 void NetSendCmdDamage(BOOL bHiPri, BYTE bPlr, DWORD dwDam)
1207 {
1208 TCmdDamage cmd;
1209
1210 cmd.bCmd = CMD_PLRDAMAGE;
1211 cmd.bPlr = bPlr;
1212 cmd.dwDam = dwDam;
1213 if (bHiPri)
1214 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1215 else
1216 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1217 }
1218
NetSendCmdMonDmg(BOOL bHiPri,WORD wMon,DWORD dwDam)1219 void NetSendCmdMonDmg(BOOL bHiPri, WORD wMon, DWORD dwDam)
1220 {
1221 TCmdMonDamage cmd;
1222
1223 cmd.bCmd = CMD_MONSTDAMAGE;
1224 cmd.wMon = wMon;
1225 cmd.dwDam = dwDam;
1226 if (bHiPri)
1227 NetSendHiPri((BYTE *)&cmd, sizeof(cmd));
1228 else
1229 NetSendLoPri((BYTE *)&cmd, sizeof(cmd));
1230 }
1231
NetSendCmdString(int pmask,const char * pszStr)1232 void NetSendCmdString(int pmask, const char *pszStr)
1233 {
1234 int dwStrLen;
1235 TCmdString cmd;
1236
1237 dwStrLen = strlen(pszStr);
1238 cmd.bCmd = CMD_STRING;
1239 strcpy(cmd.str, pszStr);
1240 multi_send_msg_packet(pmask, (BYTE *)&cmd.bCmd, dwStrLen + 2);
1241 }
1242
On_STRING2(int pnum,TCmd * pCmd)1243 static DWORD On_STRING2(int pnum, TCmd *pCmd)
1244 {
1245 TCmdString *p = (TCmdString *)pCmd;
1246
1247 int len = strlen(p->str);
1248 if (!gbBufferMsgs)
1249 SendPlrMsg(pnum, p->str);
1250
1251 return len + 2; // length of string + nul terminator + sizeof(p->bCmd)
1252 }
1253
delta_open_portal(int pnum,BYTE x,BYTE y,BYTE bLevel,dungeon_type bLType,BYTE bSetLvl)1254 static void delta_open_portal(int pnum, BYTE x, BYTE y, BYTE bLevel, dungeon_type bLType, BYTE bSetLvl)
1255 {
1256 sgbDeltaChanged = TRUE;
1257 sgJunk.portal[pnum].x = x;
1258 sgJunk.portal[pnum].y = y;
1259 sgJunk.portal[pnum].level = bLevel;
1260 sgJunk.portal[pnum].ltype = bLType;
1261 sgJunk.portal[pnum].setlvl = bSetLvl;
1262 }
1263
delta_close_portal(int pnum)1264 void delta_close_portal(int pnum)
1265 {
1266 memset(&sgJunk.portal[pnum], 0xFF, sizeof(sgJunk.portal[pnum]));
1267 sgbDeltaChanged = TRUE;
1268 }
1269
check_update_plr(int pnum)1270 static void check_update_plr(int pnum)
1271 {
1272 if (gbIsMultiplayer && pnum == myplr)
1273 pfile_update(true);
1274 }
1275
msg_errorf(const char * pszFmt,...)1276 static void msg_errorf(const char *pszFmt, ...)
1277 {
1278 static DWORD msg_err_timer;
1279 DWORD ticks;
1280 char msg[256];
1281 va_list va;
1282
1283 va_start(va, pszFmt);
1284 ticks = SDL_GetTicks();
1285 if (ticks - msg_err_timer >= 5000) {
1286 msg_err_timer = ticks;
1287 vsprintf(msg, pszFmt, va);
1288 ErrorPlrMsg(msg);
1289 }
1290 va_end(va);
1291 }
1292
On_SYNCDATA(TCmd * pCmd,int pnum)1293 static DWORD On_SYNCDATA(TCmd *pCmd, int pnum)
1294 {
1295 return sync_update(pnum, (const BYTE *)pCmd);
1296 }
1297
On_WALKXY(TCmd * pCmd,int pnum)1298 static DWORD On_WALKXY(TCmd *pCmd, int pnum)
1299 {
1300 TCmdLoc *p = (TCmdLoc *)pCmd;
1301
1302 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1303 ClrPlrPath(pnum);
1304 MakePlrPath(pnum, p->x, p->y, TRUE);
1305 plr[pnum].destAction = ACTION_NONE;
1306 }
1307
1308 return sizeof(*p);
1309 }
1310
On_ADDSTR(TCmd * pCmd,int pnum)1311 static DWORD On_ADDSTR(TCmd *pCmd, int pnum)
1312 {
1313 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1314
1315 if (gbBufferMsgs == 1)
1316 msg_send_packet(pnum, p, sizeof(*p));
1317 else if (p->wParam1 <= 256)
1318 ModifyPlrStr(pnum, p->wParam1);
1319
1320 return sizeof(*p);
1321 }
1322
On_ADDMAG(TCmd * pCmd,int pnum)1323 static DWORD On_ADDMAG(TCmd *pCmd, int pnum)
1324 {
1325 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1326
1327 if (gbBufferMsgs == 1)
1328 msg_send_packet(pnum, p, sizeof(*p));
1329 else if (p->wParam1 <= 256)
1330 ModifyPlrMag(pnum, p->wParam1);
1331
1332 return sizeof(*p);
1333 }
1334
On_ADDDEX(TCmd * pCmd,int pnum)1335 static DWORD On_ADDDEX(TCmd *pCmd, int pnum)
1336 {
1337 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1338
1339 if (gbBufferMsgs == 1)
1340 msg_send_packet(pnum, p, sizeof(*p));
1341 else if (p->wParam1 <= 256)
1342 ModifyPlrDex(pnum, p->wParam1);
1343
1344 return sizeof(*p);
1345 }
1346
On_ADDVIT(TCmd * pCmd,int pnum)1347 static DWORD On_ADDVIT(TCmd *pCmd, int pnum)
1348 {
1349 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1350
1351 if (gbBufferMsgs == 1)
1352 msg_send_packet(pnum, p, sizeof(*p));
1353 else if (p->wParam1 <= 256)
1354 ModifyPlrVit(pnum, p->wParam1);
1355
1356 return sizeof(*p);
1357 }
1358
On_SBSPELL(TCmd * pCmd,int pnum)1359 static DWORD On_SBSPELL(TCmd *pCmd, int pnum)
1360 {
1361 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1362
1363 if (gbBufferMsgs != 1) {
1364 spell_id spell = (spell_id)p->wParam1;
1365 if (currlevel != 0 || spelldata[spell].sTownSpell) {
1366 plr[pnum]._pSpell = spell;
1367 plr[pnum]._pSplType = plr[pnum]._pSBkSplType;
1368 plr[pnum]._pSplFrom = 1;
1369 plr[pnum].destAction = ACTION_SPELL;
1370 } else
1371 msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1372 }
1373
1374 return sizeof(*p);
1375 }
1376
On_GOTOGETITEM(TCmd * pCmd,int pnum)1377 static DWORD On_GOTOGETITEM(TCmd *pCmd, int pnum)
1378 {
1379 TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1380
1381 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1382 MakePlrPath(pnum, p->x, p->y, FALSE);
1383 plr[pnum].destAction = ACTION_PICKUPITEM;
1384 plr[pnum].destParam1 = p->wParam1;
1385 }
1386
1387 return sizeof(*p);
1388 }
1389
On_REQUESTGITEM(TCmd * pCmd,int pnum)1390 static DWORD On_REQUESTGITEM(TCmd *pCmd, int pnum)
1391 {
1392 TCmdGItem *p = (TCmdGItem *)pCmd;
1393
1394 if (gbBufferMsgs != 1 && i_own_level(plr[pnum].plrlevel)) {
1395 if (GetItemRecord(p->dwSeed, p->wCI, p->wIndx)) {
1396 int ii = FindGetItem(p->wIndx, p->wCI, p->dwSeed);
1397 if (ii != -1) {
1398 NetSendCmdGItem2(FALSE, CMD_GETITEM, myplr, p->bPnum, p);
1399 if (p->bPnum != myplr)
1400 SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed);
1401 else
1402 InvGetItem(myplr, ii);
1403 SetItemRecord(p->dwSeed, p->wCI, p->wIndx);
1404 } else if (!NetSendCmdReq2(CMD_REQUESTGITEM, myplr, p->bPnum, p))
1405 NetSendCmdExtra(p);
1406 }
1407 }
1408
1409 return sizeof(*p);
1410 }
1411
On_GETITEM(TCmd * pCmd,int pnum)1412 static DWORD On_GETITEM(TCmd *pCmd, int pnum)
1413 {
1414 TCmdGItem *p = (TCmdGItem *)pCmd;
1415
1416 if (gbBufferMsgs == 1)
1417 msg_send_packet(pnum, p, sizeof(*p));
1418 else {
1419 int ii = FindGetItem(p->wIndx, p->wCI, p->dwSeed);
1420 if (delta_get_item(p, p->bLevel)) {
1421 if ((currlevel == p->bLevel || p->bPnum == myplr) && p->bMaster != myplr) {
1422 if (p->bPnum == myplr) {
1423 if (currlevel != p->bLevel) {
1424 ii = SyncPutItem(myplr, plr[myplr]._px, plr[myplr]._py, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
1425 if (ii != -1)
1426 InvGetItem(myplr, ii);
1427 } else
1428 InvGetItem(myplr, ii);
1429 } else
1430 SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed);
1431 }
1432 } else
1433 NetSendCmdGItem2(TRUE, CMD_GETITEM, p->bMaster, p->bPnum, p);
1434 }
1435
1436 return sizeof(*p);
1437 }
1438
On_GOTOAGETITEM(TCmd * pCmd,int pnum)1439 static DWORD On_GOTOAGETITEM(TCmd *pCmd, int pnum)
1440 {
1441 TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1442
1443 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1444 MakePlrPath(pnum, p->x, p->y, FALSE);
1445 plr[pnum].destAction = ACTION_PICKUPAITEM;
1446 plr[pnum].destParam1 = p->wParam1;
1447 }
1448
1449 return sizeof(*p);
1450 }
1451
On_REQUESTAGITEM(TCmd * pCmd,int pnum)1452 static DWORD On_REQUESTAGITEM(TCmd *pCmd, int pnum)
1453 {
1454 TCmdGItem *p = (TCmdGItem *)pCmd;
1455
1456 if (gbBufferMsgs != 1 && i_own_level(plr[pnum].plrlevel)) {
1457 if (GetItemRecord(p->dwSeed, p->wCI, p->wIndx)) {
1458 int ii = FindGetItem(p->wIndx, p->wCI, p->dwSeed);
1459 if (ii != -1) {
1460 NetSendCmdGItem2(FALSE, CMD_AGETITEM, myplr, p->bPnum, p);
1461 if (p->bPnum != myplr)
1462 SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed);
1463 else
1464 AutoGetItem(myplr, p->bCursitem);
1465 SetItemRecord(p->dwSeed, p->wCI, p->wIndx);
1466 } else if (!NetSendCmdReq2(CMD_REQUESTAGITEM, myplr, p->bPnum, p))
1467 NetSendCmdExtra(p);
1468 }
1469 }
1470
1471 return sizeof(*p);
1472 }
1473
On_AGETITEM(TCmd * pCmd,int pnum)1474 static DWORD On_AGETITEM(TCmd *pCmd, int pnum)
1475 {
1476 TCmdGItem *p = (TCmdGItem *)pCmd;
1477
1478 if (gbBufferMsgs == 1)
1479 msg_send_packet(pnum, p, sizeof(*p));
1480 else {
1481 FindGetItem(p->wIndx, p->wCI, p->dwSeed);
1482 if (delta_get_item(p, p->bLevel)) {
1483 if ((currlevel == p->bLevel || p->bPnum == myplr) && p->bMaster != myplr) {
1484 if (p->bPnum == myplr) {
1485 if (currlevel != p->bLevel) {
1486 int ii = SyncPutItem(myplr, plr[myplr]._px, plr[myplr]._py, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
1487 if (ii != -1)
1488 AutoGetItem(myplr, ii);
1489 } else
1490 AutoGetItem(myplr, p->bCursitem);
1491 } else
1492 SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed);
1493 }
1494 } else
1495 NetSendCmdGItem2(TRUE, CMD_AGETITEM, p->bMaster, p->bPnum, p);
1496 }
1497
1498 return sizeof(*p);
1499 }
1500
On_ITEMEXTRA(TCmd * pCmd,int pnum)1501 static DWORD On_ITEMEXTRA(TCmd *pCmd, int pnum)
1502 {
1503 TCmdGItem *p = (TCmdGItem *)pCmd;
1504
1505 if (gbBufferMsgs == 1)
1506 msg_send_packet(pnum, p, sizeof(*p));
1507 else {
1508 delta_get_item(p, p->bLevel);
1509 if (currlevel == plr[pnum].plrlevel)
1510 SyncGetItem(p->x, p->y, p->wIndx, p->wCI, p->dwSeed);
1511 }
1512
1513 return sizeof(*p);
1514 }
1515
On_PUTITEM(TCmd * pCmd,int pnum)1516 static DWORD On_PUTITEM(TCmd *pCmd, int pnum)
1517 {
1518 TCmdPItem *p = (TCmdPItem *)pCmd;
1519
1520 if (gbBufferMsgs == 1)
1521 msg_send_packet(pnum, p, sizeof(*p));
1522 else if (currlevel == plr[pnum].plrlevel) {
1523 int ii;
1524 if (pnum == myplr)
1525 ii = InvPutItem(pnum, p->x, p->y);
1526 else
1527 ii = SyncPutItem(pnum, p->x, p->y, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
1528 if (ii != -1) {
1529 PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
1530 delta_put_item(p, item[ii]._ix, item[ii]._iy, plr[pnum].plrlevel);
1531 check_update_plr(pnum);
1532 }
1533 return sizeof(*p);
1534 } else {
1535 PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
1536 delta_put_item(p, p->x, p->y, plr[pnum].plrlevel);
1537 check_update_plr(pnum);
1538 }
1539
1540 return sizeof(*p);
1541 }
1542
On_SYNCPUTITEM(TCmd * pCmd,int pnum)1543 static DWORD On_SYNCPUTITEM(TCmd *pCmd, int pnum)
1544 {
1545 TCmdPItem *p = (TCmdPItem *)pCmd;
1546
1547 if (gbBufferMsgs == 1)
1548 msg_send_packet(pnum, p, sizeof(*p));
1549 else if (currlevel == plr[pnum].plrlevel) {
1550 int ii = SyncPutItem(pnum, p->x, p->y, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
1551 if (ii != -1) {
1552 PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
1553 delta_put_item(p, item[ii]._ix, item[ii]._iy, plr[pnum].plrlevel);
1554 check_update_plr(pnum);
1555 }
1556 return sizeof(*p);
1557 } else {
1558 PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
1559 delta_put_item(p, p->x, p->y, plr[pnum].plrlevel);
1560 check_update_plr(pnum);
1561 }
1562
1563 return sizeof(*p);
1564 }
1565
On_RESPAWNITEM(TCmd * pCmd,int pnum)1566 static DWORD On_RESPAWNITEM(TCmd *pCmd, int pnum)
1567 {
1568 TCmdPItem *p = (TCmdPItem *)pCmd;
1569
1570 if (gbBufferMsgs == 1)
1571 msg_send_packet(pnum, p, sizeof(*p));
1572 else {
1573 if (currlevel == plr[pnum].plrlevel && pnum != myplr) {
1574 SyncPutItem(pnum, p->x, p->y, p->wIndx, p->wCI, p->dwSeed, p->bId, p->bDur, p->bMDur, p->bCh, p->bMCh, p->wValue, p->dwBuff, p->wToHit, p->wMaxDam, p->bMinStr, p->bMinMag, p->bMinDex, p->bAC);
1575 }
1576 PutItemRecord(p->dwSeed, p->wCI, p->wIndx);
1577 delta_put_item(p, p->x, p->y, plr[pnum].plrlevel);
1578 }
1579
1580 return sizeof(*p);
1581 }
1582
On_ATTACKXY(TCmd * pCmd,int pnum)1583 static DWORD On_ATTACKXY(TCmd *pCmd, int pnum)
1584 {
1585 TCmdLoc *p = (TCmdLoc *)pCmd;
1586
1587 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1588 MakePlrPath(pnum, p->x, p->y, FALSE);
1589 plr[pnum].destAction = ACTION_ATTACK;
1590 plr[pnum].destParam1 = p->x;
1591 plr[pnum].destParam2 = p->y;
1592 }
1593
1594 return sizeof(*p);
1595 }
1596
On_SATTACKXY(TCmd * pCmd,int pnum)1597 static DWORD On_SATTACKXY(TCmd *pCmd, int pnum)
1598 {
1599 TCmdLoc *p = (TCmdLoc *)pCmd;
1600
1601 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1602 ClrPlrPath(pnum);
1603 plr[pnum].destAction = ACTION_ATTACK;
1604 plr[pnum].destParam1 = p->x;
1605 plr[pnum].destParam2 = p->y;
1606 }
1607
1608 return sizeof(*p);
1609 }
1610
On_RATTACKXY(TCmd * pCmd,int pnum)1611 static DWORD On_RATTACKXY(TCmd *pCmd, int pnum)
1612 {
1613 TCmdLoc *p = (TCmdLoc *)pCmd;
1614
1615 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1616 ClrPlrPath(pnum);
1617 plr[pnum].destAction = ACTION_RATTACK;
1618 plr[pnum].destParam1 = p->x;
1619 plr[pnum].destParam2 = p->y;
1620 }
1621
1622 return sizeof(*p);
1623 }
1624
On_SPELLXYD(TCmd * pCmd,int pnum)1625 static DWORD On_SPELLXYD(TCmd *pCmd, int pnum)
1626 {
1627 TCmdLocParam3 *p = (TCmdLocParam3 *)pCmd;
1628
1629 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1630 spell_id spell = (spell_id)p->wParam1;
1631 if (currlevel != 0 || spelldata[spell].sTownSpell) {
1632 ClrPlrPath(pnum);
1633 plr[pnum].destAction = ACTION_SPELLWALL;
1634 plr[pnum].destParam1 = p->x;
1635 plr[pnum].destParam2 = p->y;
1636 plr[pnum].destParam3 = (direction)p->wParam2;
1637 plr[pnum].destParam4 = p->wParam3;
1638 plr[pnum]._pSpell = spell;
1639 plr[pnum]._pSplType = plr[pnum]._pRSplType;
1640 plr[pnum]._pSplFrom = 0;
1641 } else
1642 msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1643 }
1644
1645 return sizeof(*p);
1646 }
1647
On_SPELLXY(TCmd * pCmd,int pnum)1648 static DWORD On_SPELLXY(TCmd *pCmd, int pnum)
1649 {
1650 TCmdLocParam2 *p = (TCmdLocParam2 *)pCmd;
1651
1652 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1653 spell_id spell = (spell_id)p->wParam1;
1654 if (currlevel != 0 || spelldata[spell].sTownSpell) {
1655 ClrPlrPath(pnum);
1656 plr[pnum].destAction = ACTION_SPELL;
1657 plr[pnum].destParam1 = p->x;
1658 plr[pnum].destParam2 = p->y;
1659 plr[pnum].destParam3 = (direction)p->wParam2;
1660 plr[pnum]._pSpell = spell;
1661 plr[pnum]._pSplType = plr[pnum]._pRSplType;
1662 plr[pnum]._pSplFrom = 0;
1663 } else
1664 msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1665 }
1666
1667 return sizeof(*p);
1668 }
1669
On_TSPELLXY(TCmd * pCmd,int pnum)1670 static DWORD On_TSPELLXY(TCmd *pCmd, int pnum)
1671 {
1672 TCmdLocParam2 *p = (TCmdLocParam2 *)pCmd;
1673
1674 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1675 spell_id spell = (spell_id)p->wParam1;
1676 if (currlevel != 0 || spelldata[spell].sTownSpell) {
1677 ClrPlrPath(pnum);
1678 plr[pnum].destAction = ACTION_SPELL;
1679 plr[pnum].destParam1 = p->x;
1680 plr[pnum].destParam2 = p->y;
1681 plr[pnum].destParam3 = (direction)p->wParam2;
1682 plr[pnum]._pSpell = spell;
1683 plr[pnum]._pSplType = plr[pnum]._pTSplType;
1684 plr[pnum]._pSplFrom = 2;
1685 } else
1686 msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1687 }
1688
1689 return sizeof(*p);
1690 }
1691
On_OPOBJXY(TCmd * pCmd,int pnum)1692 static DWORD On_OPOBJXY(TCmd *pCmd, int pnum)
1693 {
1694 TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1695
1696 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1697 if (object[p->wParam1]._oSolidFlag || object[p->wParam1]._oDoorFlag)
1698 MakePlrPath(pnum, p->x, p->y, FALSE);
1699 else
1700 MakePlrPath(pnum, p->x, p->y, TRUE);
1701 plr[pnum].destAction = ACTION_OPERATE;
1702 plr[pnum].destParam1 = p->wParam1;
1703 }
1704
1705 return sizeof(*p);
1706 }
1707
On_DISARMXY(TCmd * pCmd,int pnum)1708 static DWORD On_DISARMXY(TCmd *pCmd, int pnum)
1709 {
1710 TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1711
1712 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1713 if (object[p->wParam1]._oSolidFlag || object[p->wParam1]._oDoorFlag)
1714 MakePlrPath(pnum, p->x, p->y, FALSE);
1715 else
1716 MakePlrPath(pnum, p->x, p->y, TRUE);
1717 plr[pnum].destAction = ACTION_DISARM;
1718 plr[pnum].destParam1 = p->wParam1;
1719 }
1720
1721 return sizeof(*p);
1722 }
1723
On_OPOBJT(TCmd * pCmd,int pnum)1724 static DWORD On_OPOBJT(TCmd *pCmd, int pnum)
1725 {
1726 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1727
1728 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1729 plr[pnum].destAction = ACTION_OPERATETK;
1730 plr[pnum].destParam1 = p->wParam1;
1731 }
1732
1733 return sizeof(*p);
1734 }
1735
On_ATTACKID(TCmd * pCmd,int pnum)1736 static DWORD On_ATTACKID(TCmd *pCmd, int pnum)
1737 {
1738 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1739
1740 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1741 int distx = abs(plr[pnum]._px - monster[p->wParam1]._mfutx);
1742 int disty = abs(plr[pnum]._py - monster[p->wParam1]._mfuty);
1743 if (distx > 1 || disty > 1)
1744 MakePlrPath(pnum, monster[p->wParam1]._mfutx, monster[p->wParam1]._mfuty, FALSE);
1745 plr[pnum].destAction = ACTION_ATTACKMON;
1746 plr[pnum].destParam1 = p->wParam1;
1747 }
1748
1749 return sizeof(*p);
1750 }
1751
On_ATTACKPID(TCmd * pCmd,int pnum)1752 static DWORD On_ATTACKPID(TCmd *pCmd, int pnum)
1753 {
1754 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1755
1756 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1757 MakePlrPath(pnum, plr[p->wParam1]._pfutx, plr[p->wParam1]._pfuty, FALSE);
1758 plr[pnum].destAction = ACTION_ATTACKPLR;
1759 plr[pnum].destParam1 = p->wParam1;
1760 }
1761
1762 return sizeof(*p);
1763 }
1764
On_RATTACKID(TCmd * pCmd,int pnum)1765 static DWORD On_RATTACKID(TCmd *pCmd, int pnum)
1766 {
1767 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1768
1769 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1770 ClrPlrPath(pnum);
1771 plr[pnum].destAction = ACTION_RATTACKMON;
1772 plr[pnum].destParam1 = p->wParam1;
1773 }
1774
1775 return sizeof(*p);
1776 }
1777
On_RATTACKPID(TCmd * pCmd,int pnum)1778 static DWORD On_RATTACKPID(TCmd *pCmd, int pnum)
1779 {
1780 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1781
1782 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1783 ClrPlrPath(pnum);
1784 plr[pnum].destAction = ACTION_RATTACKPLR;
1785 plr[pnum].destParam1 = p->wParam1;
1786 }
1787
1788 return sizeof(*p);
1789 }
1790
On_SPELLID(TCmd * pCmd,int pnum)1791 static DWORD On_SPELLID(TCmd *pCmd, int pnum)
1792 {
1793 TCmdParam3 *p = (TCmdParam3 *)pCmd;
1794
1795 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1796 spell_id spell = (spell_id)p->wParam2;
1797 if (currlevel != 0 || spelldata[spell].sTownSpell) {
1798 ClrPlrPath(pnum);
1799 plr[pnum].destAction = ACTION_SPELLMON;
1800 plr[pnum].destParam1 = p->wParam1;
1801 plr[pnum].destParam2 = p->wParam3;
1802 plr[pnum]._pSpell = spell;
1803 plr[pnum]._pSplType = plr[pnum]._pRSplType;
1804 plr[pnum]._pSplFrom = 0;
1805 } else
1806 msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1807 }
1808
1809 return sizeof(*p);
1810 }
1811
On_SPELLPID(TCmd * pCmd,int pnum)1812 static DWORD On_SPELLPID(TCmd *pCmd, int pnum)
1813 {
1814 TCmdParam3 *p = (TCmdParam3 *)pCmd;
1815
1816 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1817 spell_id spell = (spell_id)p->wParam2;
1818 if (currlevel != 0 || spelldata[spell].sTownSpell) {
1819 ClrPlrPath(pnum);
1820 plr[pnum].destAction = ACTION_SPELLPLR;
1821 plr[pnum].destParam1 = p->wParam1;
1822 plr[pnum].destParam2 = p->wParam3;
1823 plr[pnum]._pSpell = spell;
1824 plr[pnum]._pSplType = plr[pnum]._pRSplType;
1825 plr[pnum]._pSplFrom = 0;
1826 } else
1827 msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1828 }
1829
1830 return sizeof(*p);
1831 }
1832
On_TSPELLID(TCmd * pCmd,int pnum)1833 static DWORD On_TSPELLID(TCmd *pCmd, int pnum)
1834 {
1835 TCmdParam3 *p = (TCmdParam3 *)pCmd;
1836
1837 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1838 spell_id spell = (spell_id)p->wParam2;
1839 if (currlevel != 0 || spelldata[spell].sTownSpell) {
1840 ClrPlrPath(pnum);
1841 plr[pnum].destAction = ACTION_SPELLMON;
1842 plr[pnum].destParam1 = p->wParam1;
1843 plr[pnum].destParam2 = p->wParam3;
1844 plr[pnum]._pSpell = spell;
1845 plr[pnum]._pSplType = plr[pnum]._pTSplType;
1846 plr[pnum]._pSplFrom = 2;
1847 } else
1848 msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1849 }
1850
1851 return sizeof(*p);
1852 }
1853
On_TSPELLPID(TCmd * pCmd,int pnum)1854 static DWORD On_TSPELLPID(TCmd *pCmd, int pnum)
1855 {
1856 TCmdParam3 *p = (TCmdParam3 *)pCmd;
1857
1858 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1859 spell_id spell = (spell_id)p->wParam2;
1860 if (currlevel != 0 || spelldata[spell].sTownSpell) {
1861 ClrPlrPath(pnum);
1862 plr[pnum].destAction = ACTION_SPELLPLR;
1863 plr[pnum].destParam1 = p->wParam1;
1864 plr[pnum].destParam2 = p->wParam3;
1865 plr[pnum]._pSpell = spell;
1866 plr[pnum]._pSplType = plr[pnum]._pTSplType;
1867 plr[pnum]._pSplFrom = 2;
1868 } else
1869 msg_errorf("%s has cast an illegal spell.", plr[pnum]._pName);
1870 }
1871
1872 return sizeof(*p);
1873 }
1874
On_KNOCKBACK(TCmd * pCmd,int pnum)1875 static DWORD On_KNOCKBACK(TCmd *pCmd, int pnum)
1876 {
1877 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1878
1879 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1880 M_GetKnockback(p->wParam1);
1881 M_StartHit(p->wParam1, pnum, 0);
1882 }
1883
1884 return sizeof(*p);
1885 }
1886
On_RESURRECT(TCmd * pCmd,int pnum)1887 static DWORD On_RESURRECT(TCmd *pCmd, int pnum)
1888 {
1889 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1890
1891 if (gbBufferMsgs == 1)
1892 msg_send_packet(pnum, p, sizeof(*p));
1893 else {
1894 DoResurrect(pnum, p->wParam1);
1895 check_update_plr(pnum);
1896 }
1897
1898 return sizeof(*p);
1899 }
1900
On_HEALOTHER(TCmd * pCmd,int pnum)1901 static DWORD On_HEALOTHER(TCmd *pCmd, int pnum)
1902 {
1903 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1904
1905 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel)
1906 DoHealOther(pnum, p->wParam1);
1907
1908 return sizeof(*p);
1909 }
1910
On_TALKXY(TCmd * pCmd,int pnum)1911 static DWORD On_TALKXY(TCmd *pCmd, int pnum)
1912 {
1913 TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1914
1915 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel) {
1916 MakePlrPath(pnum, p->x, p->y, FALSE);
1917 plr[pnum].destAction = ACTION_TALK;
1918 plr[pnum].destParam1 = p->wParam1;
1919 }
1920
1921 return sizeof(*p);
1922 }
1923
On_NEWLVL(TCmd * pCmd,int pnum)1924 static DWORD On_NEWLVL(TCmd *pCmd, int pnum)
1925 {
1926 TCmdParam2 *p = (TCmdParam2 *)pCmd;
1927
1928 if (gbBufferMsgs == 1)
1929 msg_send_packet(pnum, p, sizeof(*p));
1930 else if (pnum != myplr)
1931 StartNewLvl(pnum, p->wParam1, p->wParam2);
1932
1933 return sizeof(*p);
1934 }
1935
On_WARP(TCmd * pCmd,int pnum)1936 static DWORD On_WARP(TCmd *pCmd, int pnum)
1937 {
1938 TCmdParam1 *p = (TCmdParam1 *)pCmd;
1939
1940 if (gbBufferMsgs == 1)
1941 msg_send_packet(pnum, p, sizeof(*p));
1942 else {
1943 StartWarpLvl(pnum, p->wParam1);
1944 }
1945
1946 return sizeof(*p);
1947 }
1948
On_MONSTDEATH(TCmd * pCmd,int pnum)1949 static DWORD On_MONSTDEATH(TCmd *pCmd, int pnum)
1950 {
1951 TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1952
1953 if (gbBufferMsgs == 1)
1954 msg_send_packet(pnum, p, sizeof(*p));
1955 else if (pnum != myplr) {
1956 if (currlevel == plr[pnum].plrlevel)
1957 M_SyncStartKill(p->wParam1, p->x, p->y, pnum);
1958 delta_kill_monster(p->wParam1, p->x, p->y, plr[pnum].plrlevel);
1959 }
1960
1961 return sizeof(*p);
1962 }
1963
On_KILLGOLEM(TCmd * pCmd,int pnum)1964 static DWORD On_KILLGOLEM(TCmd *pCmd, int pnum)
1965 {
1966 TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
1967
1968 if (gbBufferMsgs == 1)
1969 msg_send_packet(pnum, p, sizeof(*p));
1970 else if (pnum != myplr) {
1971 if (currlevel == p->wParam1)
1972 M_SyncStartKill(pnum, p->x, p->y, pnum);
1973 delta_kill_monster(pnum, p->x, p->y, plr[pnum].plrlevel);
1974 }
1975
1976 return sizeof(*p);
1977 }
1978
On_AWAKEGOLEM(TCmd * pCmd,int pnum)1979 static DWORD On_AWAKEGOLEM(TCmd *pCmd, int pnum)
1980 {
1981 TCmdGolem *p = (TCmdGolem *)pCmd;
1982
1983 if (gbBufferMsgs == 1)
1984 msg_send_packet(pnum, p, sizeof(*p));
1985 else if (currlevel != plr[pnum].plrlevel)
1986 delta_sync_golem(p, pnum, p->_currlevel);
1987 else if (pnum != myplr) {
1988 int i;
1989 // check if this player already has an active golem
1990 BOOL addGolem = TRUE;
1991 for (i = 0; i < nummissiles; i++) {
1992 int mi = missileactive[i];
1993 if (missile[mi]._mitype == MIS_GOLEM && missile[mi]._misource == pnum) {
1994 addGolem = FALSE;
1995 // BUGFIX: break, don't need to check the rest
1996 }
1997 }
1998 if (addGolem)
1999 AddMissile(plr[pnum]._px, plr[pnum]._py, p->_mx, p->_my, p->_mdir, MIS_GOLEM, TARGET_MONSTERS, pnum, 0, 1);
2000 }
2001
2002 return sizeof(*p);
2003 }
2004
On_MONSTDAMAGE(TCmd * pCmd,int pnum)2005 static DWORD On_MONSTDAMAGE(TCmd *pCmd, int pnum)
2006 {
2007 TCmdMonDamage *p = (TCmdMonDamage *)pCmd;
2008
2009 if (gbBufferMsgs == 1)
2010 msg_send_packet(pnum, p, sizeof(*p)); // BUGFIX: change to sizeof(*p) or it still uses TCmdParam2 size for hellfire (fixed)
2011 else if (pnum != myplr) {
2012 if (currlevel == plr[pnum].plrlevel) {
2013 monster[p->wMon].mWhoHit |= 1 << pnum;
2014 if (monster[p->wMon]._mhitpoints > 0) {
2015 monster[p->wMon]._mhitpoints -= p->dwDam;
2016 if ((monster[p->wMon]._mhitpoints >> 6) < 1)
2017 monster[p->wMon]._mhitpoints = 1 << 6;
2018 delta_monster_hp(p->wMon, monster[p->wMon]._mhitpoints, plr[pnum].plrlevel);
2019 }
2020 }
2021 }
2022
2023 return sizeof(*p);
2024 }
2025
On_PLRDEAD(TCmd * pCmd,int pnum)2026 static DWORD On_PLRDEAD(TCmd *pCmd, int pnum)
2027 {
2028 TCmdParam1 *p = (TCmdParam1 *)pCmd;
2029
2030 if (gbBufferMsgs == 1)
2031 msg_send_packet(pnum, p, sizeof(*p));
2032 else if (pnum != myplr)
2033 StartPlayerKill(pnum, p->wParam1);
2034 else
2035 check_update_plr(pnum);
2036
2037 return sizeof(*p);
2038 }
2039
On_PLRDAMAGE(TCmd * pCmd,int pnum)2040 static DWORD On_PLRDAMAGE(TCmd *pCmd, int pnum)
2041 {
2042 TCmdDamage *p = (TCmdDamage *)pCmd;
2043
2044 if (p->bPlr == myplr && currlevel != 0 && gbBufferMsgs != 1) {
2045 if (currlevel == plr[pnum].plrlevel && p->dwDam <= 192000 && plr[myplr]._pHitPoints >> 6 > 0) {
2046 drawhpflag = TRUE;
2047 plr[myplr]._pHitPoints -= p->dwDam;
2048 plr[myplr]._pHPBase -= p->dwDam;
2049 if (plr[myplr]._pHitPoints > plr[myplr]._pMaxHP) {
2050 plr[myplr]._pHitPoints = plr[myplr]._pMaxHP;
2051 plr[myplr]._pHPBase = plr[myplr]._pMaxHPBase;
2052 }
2053 if (plr[myplr]._pHitPoints >> 6 <= 0) {
2054 SyncPlrKill(myplr, 1);
2055 }
2056 }
2057 }
2058
2059 return sizeof(*p);
2060 }
2061
On_OPENDOOR(TCmd * pCmd,int pnum)2062 static DWORD On_OPENDOOR(TCmd *pCmd, int pnum)
2063 {
2064 TCmdParam1 *p = (TCmdParam1 *)pCmd;
2065
2066 if (gbBufferMsgs == 1)
2067 msg_send_packet(pnum, p, sizeof(*p));
2068 else {
2069 if (currlevel == plr[pnum].plrlevel)
2070 SyncOpObject(pnum, CMD_OPENDOOR, p->wParam1);
2071 delta_sync_object(p->wParam1, CMD_OPENDOOR, plr[pnum].plrlevel);
2072 }
2073
2074 return sizeof(*p);
2075 }
2076
On_CLOSEDOOR(TCmd * pCmd,int pnum)2077 static DWORD On_CLOSEDOOR(TCmd *pCmd, int pnum)
2078 {
2079 TCmdParam1 *p = (TCmdParam1 *)pCmd;
2080
2081 if (gbBufferMsgs == 1)
2082 msg_send_packet(pnum, p, sizeof(*p));
2083 else {
2084 if (currlevel == plr[pnum].plrlevel)
2085 SyncOpObject(pnum, CMD_CLOSEDOOR, p->wParam1);
2086 delta_sync_object(p->wParam1, CMD_CLOSEDOOR, plr[pnum].plrlevel);
2087 }
2088
2089 return sizeof(*p);
2090 }
2091
On_OPERATEOBJ(TCmd * pCmd,int pnum)2092 static DWORD On_OPERATEOBJ(TCmd *pCmd, int pnum)
2093 {
2094 TCmdParam1 *p = (TCmdParam1 *)pCmd;
2095
2096 if (gbBufferMsgs == 1)
2097 msg_send_packet(pnum, p, sizeof(*p));
2098 else {
2099 if (currlevel == plr[pnum].plrlevel)
2100 SyncOpObject(pnum, CMD_OPERATEOBJ, p->wParam1);
2101 delta_sync_object(p->wParam1, CMD_OPERATEOBJ, plr[pnum].plrlevel);
2102 }
2103
2104 return sizeof(*p);
2105 }
2106
On_PLROPOBJ(TCmd * pCmd,int pnum)2107 static DWORD On_PLROPOBJ(TCmd *pCmd, int pnum)
2108 {
2109 TCmdParam2 *p = (TCmdParam2 *)pCmd;
2110
2111 if (gbBufferMsgs == 1)
2112 msg_send_packet(pnum, p, sizeof(*p));
2113 else {
2114 if (currlevel == plr[pnum].plrlevel)
2115 SyncOpObject(p->wParam1, CMD_PLROPOBJ, p->wParam2);
2116 delta_sync_object(p->wParam2, CMD_PLROPOBJ, plr[pnum].plrlevel);
2117 }
2118
2119 return sizeof(*p);
2120 }
2121
On_BREAKOBJ(TCmd * pCmd,int pnum)2122 static DWORD On_BREAKOBJ(TCmd *pCmd, int pnum)
2123 {
2124 TCmdParam2 *p = (TCmdParam2 *)pCmd;
2125
2126 if (gbBufferMsgs == 1)
2127 msg_send_packet(pnum, p, sizeof(*p));
2128 else {
2129 if (currlevel == plr[pnum].plrlevel)
2130 SyncBreakObj(p->wParam1, p->wParam2);
2131 delta_sync_object(p->wParam2, CMD_BREAKOBJ, plr[pnum].plrlevel);
2132 }
2133
2134 return sizeof(*p);
2135 }
2136
On_CHANGEPLRITEMS(TCmd * pCmd,int pnum)2137 static DWORD On_CHANGEPLRITEMS(TCmd *pCmd, int pnum)
2138 {
2139 TCmdChItem *p = (TCmdChItem *)pCmd;
2140
2141 if (gbBufferMsgs == 1)
2142 msg_send_packet(pnum, p, sizeof(*p));
2143 else if (pnum != myplr)
2144 CheckInvSwap(pnum, p->bLoc, p->wIndx, p->wCI, p->dwSeed, p->bId, p->dwBuff);
2145
2146 return sizeof(*p);
2147 }
2148
On_DELPLRITEMS(TCmd * pCmd,int pnum)2149 static DWORD On_DELPLRITEMS(TCmd *pCmd, int pnum)
2150 {
2151 TCmdDelItem *p = (TCmdDelItem *)pCmd;
2152
2153 if (gbBufferMsgs == 1)
2154 msg_send_packet(pnum, p, sizeof(*p));
2155 else if (pnum != myplr)
2156 inv_update_rem_item(pnum, p->bLoc);
2157
2158 return sizeof(*p);
2159 }
2160
On_PLRLEVEL(TCmd * pCmd,int pnum)2161 static DWORD On_PLRLEVEL(TCmd *pCmd, int pnum)
2162 {
2163 TCmdParam1 *p = (TCmdParam1 *)pCmd;
2164
2165 if (gbBufferMsgs == 1)
2166 msg_send_packet(pnum, p, sizeof(*p));
2167 else if (p->wParam1 <= MAXCHARLEVEL && pnum != myplr)
2168 plr[pnum]._pLevel = p->wParam1;
2169
2170 return sizeof(*p);
2171 }
2172
On_DROPITEM(TCmd * pCmd,int pnum)2173 static DWORD On_DROPITEM(TCmd *pCmd, int pnum)
2174 {
2175 TCmdPItem *p = (TCmdPItem *)pCmd;
2176
2177 if (gbBufferMsgs == 1)
2178 msg_send_packet(pnum, p, sizeof(*p));
2179 else
2180 delta_put_item(p, p->x, p->y, plr[pnum].plrlevel);
2181
2182 return sizeof(*p);
2183 }
2184
On_SEND_PLRINFO(TCmd * pCmd,int pnum)2185 static DWORD On_SEND_PLRINFO(TCmd *pCmd, int pnum)
2186 {
2187 TCmdPlrInfoHdr *p = (TCmdPlrInfoHdr *)pCmd;
2188
2189 if (gbBufferMsgs == 1)
2190 msg_send_packet(pnum, p, p->wBytes + sizeof(*p));
2191 else
2192 recv_plrinfo(pnum, p, p->bCmd == CMD_ACK_PLRINFO);
2193
2194 return p->wBytes + sizeof(*p);
2195 }
2196
On_ACK_PLRINFO(TCmd * pCmd,int pnum)2197 static DWORD On_ACK_PLRINFO(TCmd *pCmd, int pnum)
2198 {
2199 return On_SEND_PLRINFO(pCmd, pnum);
2200 }
2201
On_PLAYER_JOINLEVEL(TCmd * pCmd,int pnum)2202 static DWORD On_PLAYER_JOINLEVEL(TCmd *pCmd, int pnum)
2203 {
2204 TCmdLocParam1 *p = (TCmdLocParam1 *)pCmd;
2205
2206 if (gbBufferMsgs == 1)
2207 msg_send_packet(pnum, p, sizeof(*p));
2208 else {
2209 plr[pnum]._pLvlChanging = FALSE;
2210 if (plr[pnum]._pName[0] != 0 && !plr[pnum].plractive) {
2211 plr[pnum].plractive = TRUE;
2212 gbActivePlayers++;
2213 EventPlrMsg("Player '%s' (level %d) just joined the game", plr[pnum]._pName, plr[pnum]._pLevel);
2214 }
2215
2216 if (plr[pnum].plractive && myplr != pnum) {
2217 plr[pnum]._px = p->x;
2218 plr[pnum]._py = p->y;
2219 plr[pnum].plrlevel = p->wParam1;
2220 plr[pnum]._pGFXLoad = 0;
2221 if (currlevel == plr[pnum].plrlevel) {
2222 LoadPlrGFX(pnum, PFILE_STAND);
2223 SyncInitPlr(pnum);
2224 if ((plr[pnum]._pHitPoints >> 6) > 0)
2225 StartStand(pnum, DIR_S);
2226 else {
2227 plr[pnum]._pgfxnum = 0;
2228 LoadPlrGFX(pnum, PFILE_DEATH);
2229 plr[pnum]._pmode = PM_DEATH;
2230 NewPlrAnim(pnum, plr[pnum]._pDAnim[DIR_S], plr[pnum]._pDFrames, 1, plr[pnum]._pDWidth);
2231 plr[pnum]._pAnimFrame = plr[pnum]._pAnimLen - 1;
2232 plr[pnum]._pVar8 = plr[pnum]._pAnimLen << 1;
2233 dFlags[plr[pnum]._px][plr[pnum]._py] |= BFLAG_DEAD_PLAYER;
2234 }
2235
2236 plr[pnum]._pvid = AddVision(plr[pnum]._px, plr[pnum]._py, plr[pnum]._pLightRad, pnum == myplr);
2237 plr[pnum]._plid = NO_LIGHT;
2238 }
2239 }
2240 }
2241
2242 return sizeof(*p);
2243 }
2244
On_ACTIVATEPORTAL(TCmd * pCmd,int pnum)2245 static DWORD On_ACTIVATEPORTAL(TCmd *pCmd, int pnum)
2246 {
2247 TCmdLocParam3 *p = (TCmdLocParam3 *)pCmd;
2248
2249 if (gbBufferMsgs == 1)
2250 msg_send_packet(pnum, p, sizeof(*p));
2251 else {
2252 ActivatePortal(pnum, p->x, p->y, p->wParam1, (dungeon_type)p->wParam2, p->wParam3);
2253 if (pnum != myplr) {
2254 if (currlevel == 0)
2255 AddInTownPortal(pnum);
2256 else if (currlevel == plr[pnum].plrlevel) {
2257 BOOL addPortal = TRUE;
2258 for (int i = 0; i < nummissiles; i++) {
2259 int mi = missileactive[i];
2260 if (missile[mi]._mitype == MIS_TOWN && missile[mi]._misource == pnum) {
2261 addPortal = FALSE;
2262 // CODEFIX: break
2263 }
2264 }
2265 if (addPortal)
2266 AddWarpMissile(pnum, p->x, p->y);
2267 } else
2268 RemovePortalMissile(pnum);
2269 }
2270 delta_open_portal(pnum, p->x, p->y, p->wParam1, (dungeon_type)p->wParam2, p->wParam3);
2271 }
2272
2273 return sizeof(*p);
2274 }
2275
On_DEACTIVATEPORTAL(TCmd * pCmd,int pnum)2276 static DWORD On_DEACTIVATEPORTAL(TCmd *pCmd, int pnum)
2277 {
2278 if (gbBufferMsgs == 1)
2279 msg_send_packet(pnum, pCmd, sizeof(*pCmd));
2280 else {
2281 if (PortalOnLevel(pnum))
2282 RemovePortalMissile(pnum);
2283 DeactivatePortal(pnum);
2284 delta_close_portal(pnum);
2285 }
2286
2287 return sizeof(*pCmd);
2288 }
2289
On_RETOWN(TCmd * pCmd,int pnum)2290 static DWORD On_RETOWN(TCmd *pCmd, int pnum)
2291 {
2292 if (gbBufferMsgs == 1)
2293 msg_send_packet(pnum, pCmd, sizeof(*pCmd));
2294 else {
2295 if (pnum == myplr) {
2296 deathflag = FALSE;
2297 gamemenu_off();
2298 }
2299 RestartTownLvl(pnum);
2300 }
2301
2302 return sizeof(*pCmd);
2303 }
2304
On_SETSTR(TCmd * pCmd,int pnum)2305 static DWORD On_SETSTR(TCmd *pCmd, int pnum)
2306 {
2307 TCmdParam1 *p = (TCmdParam1 *)pCmd;
2308
2309 if (gbBufferMsgs == 1)
2310 msg_send_packet(pnum, p, sizeof(*p));
2311 else if (p->wParam1 <= 750 && pnum != myplr)
2312 SetPlrStr(pnum, p->wParam1);
2313
2314 return sizeof(*p);
2315 }
2316
On_SETDEX(TCmd * pCmd,int pnum)2317 static DWORD On_SETDEX(TCmd *pCmd, int pnum)
2318 {
2319 TCmdParam1 *p = (TCmdParam1 *)pCmd;
2320
2321 if (gbBufferMsgs == 1)
2322 msg_send_packet(pnum, p, sizeof(*p));
2323 else if (p->wParam1 <= 750 && pnum != myplr)
2324 SetPlrDex(pnum, p->wParam1);
2325
2326 return sizeof(*p);
2327 }
2328
On_SETMAG(TCmd * pCmd,int pnum)2329 static DWORD On_SETMAG(TCmd *pCmd, int pnum)
2330 {
2331 TCmdParam1 *p = (TCmdParam1 *)pCmd;
2332
2333 if (gbBufferMsgs == 1)
2334 msg_send_packet(pnum, p, sizeof(*p));
2335 else if (p->wParam1 <= 750 && pnum != myplr)
2336 SetPlrMag(pnum, p->wParam1);
2337
2338 return sizeof(*p);
2339 }
2340
On_SETVIT(TCmd * pCmd,int pnum)2341 static DWORD On_SETVIT(TCmd *pCmd, int pnum)
2342 {
2343 TCmdParam1 *p = (TCmdParam1 *)pCmd;
2344
2345 if (gbBufferMsgs == 1)
2346 msg_send_packet(pnum, p, sizeof(*p));
2347 else if (p->wParam1 <= 750 && pnum != myplr)
2348 SetPlrVit(pnum, p->wParam1);
2349
2350 return sizeof(*p);
2351 }
2352
On_STRING(TCmd * pCmd,int pnum)2353 static DWORD On_STRING(TCmd *pCmd, int pnum)
2354 {
2355 return On_STRING2(pnum, pCmd);
2356 }
2357
On_SYNCQUEST(TCmd * pCmd,int pnum)2358 static DWORD On_SYNCQUEST(TCmd *pCmd, int pnum)
2359 {
2360 TCmdQuest *p = (TCmdQuest *)pCmd;
2361
2362 if (gbBufferMsgs == 1)
2363 msg_send_packet(pnum, p, sizeof(*p));
2364 else {
2365 if (pnum != myplr)
2366 SetMultiQuest(p->q, p->qstate, p->qlog, p->qvar1);
2367 sgbDeltaChanged = TRUE;
2368 }
2369
2370 return sizeof(*p);
2371 }
2372
On_ENDREFLECT(TCmd * pCmd,int pnum)2373 static DWORD On_ENDREFLECT(TCmd *pCmd, int pnum)
2374 {
2375 if (gbBufferMsgs != 1 && pnum != myplr && currlevel == plr[pnum].plrlevel) {
2376 for (int i = 0; i < nummissiles; i++) {
2377 int mi = missileactive[i];
2378 if (missile[mi]._mitype == MIS_REFLECT && missile[mi]._misource == pnum) {
2379 ClearMissileSpot(mi);
2380 DeleteMissile(mi, i);
2381 }
2382 }
2383 }
2384
2385 return sizeof(*pCmd);
2386 }
2387
On_ENDSHIELD(TCmd * pCmd,int pnum)2388 static DWORD On_ENDSHIELD(TCmd *pCmd, int pnum)
2389 {
2390 if (gbBufferMsgs != 1 && pnum != myplr && currlevel == plr[pnum].plrlevel) {
2391 for (int i = 0; i < nummissiles; i++) {
2392 int mi = missileactive[i];
2393 if (missile[mi]._mitype == MIS_MANASHIELD && missile[mi]._misource == pnum) {
2394 ClearMissileSpot(mi);
2395 DeleteMissile(mi, i);
2396 }
2397 }
2398 }
2399
2400 return sizeof(*pCmd);
2401 }
2402
On_CHEAT_EXPERIENCE(TCmd * pCmd,int pnum)2403 static DWORD On_CHEAT_EXPERIENCE(TCmd *pCmd, int pnum)
2404 {
2405 #ifdef _DEBUG
2406 if (gbBufferMsgs == 1)
2407 msg_send_packet(pnum, pCmd, sizeof(*pCmd));
2408 else if (plr[pnum]._pLevel < MAXCHARLEVEL - 1) {
2409 plr[pnum]._pExperience = plr[pnum]._pNextExper;
2410 if (sgOptions.Gameplay.bExperienceBar) {
2411 force_redraw = 255;
2412 }
2413 NextPlrLevel(pnum);
2414 }
2415 #endif
2416 return sizeof(*pCmd);
2417 }
2418
On_CHEAT_SPELL_LEVEL(TCmd * pCmd,int pnum)2419 static DWORD On_CHEAT_SPELL_LEVEL(TCmd *pCmd, int pnum)
2420 {
2421 #ifdef _DEBUG
2422 if (gbBufferMsgs == 1)
2423 msg_send_packet(pnum, pCmd, sizeof(*pCmd));
2424 else
2425 plr[pnum]._pSplLvl[plr[pnum]._pRSpell]++;
2426 #endif
2427 return sizeof(*pCmd);
2428 }
2429
On_DEBUG(TCmd * pCmd,int pnum)2430 static DWORD On_DEBUG(TCmd *pCmd, int pnum)
2431 {
2432 return sizeof(*pCmd);
2433 }
2434
On_NOVA(TCmd * pCmd,int pnum)2435 static DWORD On_NOVA(TCmd *pCmd, int pnum)
2436 {
2437 TCmdLoc *p = (TCmdLoc *)pCmd;
2438
2439 if (gbBufferMsgs != 1 && currlevel == plr[pnum].plrlevel && pnum != myplr) {
2440 ClrPlrPath(pnum);
2441 plr[pnum]._pSpell = SPL_NOVA;
2442 plr[pnum]._pSplType = RSPLTYPE_INVALID;
2443 plr[pnum]._pSplFrom = 3;
2444 plr[pnum].destAction = ACTION_SPELL;
2445 plr[pnum].destParam1 = p->x;
2446 plr[pnum].destParam2 = p->y;
2447 }
2448
2449 return sizeof(*p);
2450 }
2451
On_SETSHIELD(TCmd * pCmd,int pnum)2452 static DWORD On_SETSHIELD(TCmd *pCmd, int pnum)
2453 {
2454 if (gbBufferMsgs != 1)
2455 plr[pnum].pManaShield = TRUE;
2456
2457 return sizeof(*pCmd);
2458 }
2459
On_REMSHIELD(TCmd * pCmd,int pnum)2460 static DWORD On_REMSHIELD(TCmd *pCmd, int pnum)
2461 {
2462 if (gbBufferMsgs != 1)
2463 plr[pnum].pManaShield = FALSE;
2464
2465 return sizeof(*pCmd);
2466 }
2467
On_REFLECT(TCmd * pCmd,int pnum)2468 static DWORD On_REFLECT(TCmd *pCmd, int pnum)
2469 {
2470 if (gbBufferMsgs != 1 && pnum != myplr && currlevel == plr[pnum].plrlevel) {
2471 for (int i = 0; i < nummissiles; i++) {
2472 int mx = missileactive[i];
2473 if (missile[mx]._mitype == MIS_REFLECT && missile[mx]._misource == pnum) {
2474 ClearMissileSpot(mx);
2475 DeleteMissile(mx, i);
2476 }
2477 }
2478 }
2479
2480 return sizeof(*pCmd);
2481 }
2482
On_NAKRUL(TCmd * pCmd,int pnum)2483 static DWORD On_NAKRUL(TCmd *pCmd, int pnum)
2484 {
2485 if (gbBufferMsgs != 1) {
2486 operate_lv24_lever();
2487 IsUberRoomOpened = 1;
2488 quests[Q_NAKRUL]._qactive = 3;
2489 monster_some_crypt();
2490 }
2491 return sizeof(*pCmd);
2492 }
2493
On_OPENHIVE(TCmd * pCmd,int pnum)2494 static DWORD On_OPENHIVE(TCmd *pCmd, int pnum)
2495 {
2496 TCmdLocParam2 *p = (TCmdLocParam2 *)pCmd;
2497 if (gbBufferMsgs != 1) {
2498 AddMissile(p->x, p->y, p->wParam1, p->wParam2, 0, MIS_HIVEEXP2, TARGET_MONSTERS, pnum, 0, 0);
2499 TownOpenHive();
2500 }
2501 return sizeof(*p);
2502 }
2503
On_OPENCRYPT(TCmd * pCmd,int pnum)2504 static DWORD On_OPENCRYPT(TCmd *pCmd, int pnum)
2505 {
2506 if (gbBufferMsgs != 1) {
2507 TownOpenGrave();
2508 InitTownTriggers();
2509 if (currlevel == 0)
2510 PlaySFX(IS_SARC);
2511 }
2512 return sizeof(*pCmd);
2513 }
2514
ParseCmd(int pnum,TCmd * pCmd)2515 DWORD ParseCmd(int pnum, TCmd *pCmd)
2516 {
2517 sbLastCmd = pCmd->bCmd;
2518 if (sgwPackPlrOffsetTbl[pnum] != 0 && sbLastCmd != CMD_ACK_PLRINFO && sbLastCmd != CMD_SEND_PLRINFO)
2519 return 0;
2520
2521 switch (pCmd->bCmd) {
2522 case CMD_SYNCDATA:
2523 return On_SYNCDATA(pCmd, pnum);
2524 case CMD_WALKXY:
2525 return On_WALKXY(pCmd, pnum);
2526 case CMD_ADDSTR:
2527 return On_ADDSTR(pCmd, pnum);
2528 case CMD_ADDDEX:
2529 return On_ADDDEX(pCmd, pnum);
2530 case CMD_ADDMAG:
2531 return On_ADDMAG(pCmd, pnum);
2532 case CMD_ADDVIT:
2533 return On_ADDVIT(pCmd, pnum);
2534 case CMD_SBSPELL:
2535 return On_SBSPELL(pCmd, pnum);
2536 case CMD_GOTOGETITEM:
2537 return On_GOTOGETITEM(pCmd, pnum);
2538 case CMD_REQUESTGITEM:
2539 return On_REQUESTGITEM(pCmd, pnum);
2540 case CMD_GETITEM:
2541 return On_GETITEM(pCmd, pnum);
2542 case CMD_GOTOAGETITEM:
2543 return On_GOTOAGETITEM(pCmd, pnum);
2544 case CMD_REQUESTAGITEM:
2545 return On_REQUESTAGITEM(pCmd, pnum);
2546 case CMD_AGETITEM:
2547 return On_AGETITEM(pCmd, pnum);
2548 case CMD_ITEMEXTRA:
2549 return On_ITEMEXTRA(pCmd, pnum);
2550 case CMD_PUTITEM:
2551 return On_PUTITEM(pCmd, pnum);
2552 case CMD_SYNCPUTITEM:
2553 return On_SYNCPUTITEM(pCmd, pnum);
2554 case CMD_RESPAWNITEM:
2555 return On_RESPAWNITEM(pCmd, pnum);
2556 case CMD_ATTACKXY:
2557 return On_ATTACKXY(pCmd, pnum);
2558 case CMD_SATTACKXY:
2559 return On_SATTACKXY(pCmd, pnum);
2560 case CMD_RATTACKXY:
2561 return On_RATTACKXY(pCmd, pnum);
2562 case CMD_SPELLXYD:
2563 return On_SPELLXYD(pCmd, pnum);
2564 case CMD_SPELLXY:
2565 return On_SPELLXY(pCmd, pnum);
2566 case CMD_TSPELLXY:
2567 return On_TSPELLXY(pCmd, pnum);
2568 case CMD_OPOBJXY:
2569 return On_OPOBJXY(pCmd, pnum);
2570 case CMD_DISARMXY:
2571 return On_DISARMXY(pCmd, pnum);
2572 case CMD_OPOBJT:
2573 return On_OPOBJT(pCmd, pnum);
2574 case CMD_ATTACKID:
2575 return On_ATTACKID(pCmd, pnum);
2576 case CMD_ATTACKPID:
2577 return On_ATTACKPID(pCmd, pnum);
2578 case CMD_RATTACKID:
2579 return On_RATTACKID(pCmd, pnum);
2580 case CMD_RATTACKPID:
2581 return On_RATTACKPID(pCmd, pnum);
2582 case CMD_SPELLID:
2583 return On_SPELLID(pCmd, pnum);
2584 case CMD_SPELLPID:
2585 return On_SPELLPID(pCmd, pnum);
2586 case CMD_TSPELLID:
2587 return On_TSPELLID(pCmd, pnum);
2588 case CMD_TSPELLPID:
2589 return On_TSPELLPID(pCmd, pnum);
2590 case CMD_KNOCKBACK:
2591 return On_KNOCKBACK(pCmd, pnum);
2592 case CMD_RESURRECT:
2593 return On_RESURRECT(pCmd, pnum);
2594 case CMD_HEALOTHER:
2595 return On_HEALOTHER(pCmd, pnum);
2596 case CMD_TALKXY:
2597 return On_TALKXY(pCmd, pnum);
2598 case CMD_DEBUG:
2599 return On_DEBUG(pCmd, pnum);
2600 case CMD_NEWLVL:
2601 return On_NEWLVL(pCmd, pnum);
2602 case CMD_WARP:
2603 return On_WARP(pCmd, pnum);
2604 case CMD_MONSTDEATH:
2605 return On_MONSTDEATH(pCmd, pnum);
2606 case CMD_KILLGOLEM:
2607 return On_KILLGOLEM(pCmd, pnum);
2608 case CMD_AWAKEGOLEM:
2609 return On_AWAKEGOLEM(pCmd, pnum);
2610 case CMD_MONSTDAMAGE:
2611 return On_MONSTDAMAGE(pCmd, pnum);
2612 case CMD_PLRDEAD:
2613 return On_PLRDEAD(pCmd, pnum);
2614 case CMD_PLRDAMAGE:
2615 return On_PLRDAMAGE(pCmd, pnum);
2616 case CMD_OPENDOOR:
2617 return On_OPENDOOR(pCmd, pnum);
2618 case CMD_CLOSEDOOR:
2619 return On_CLOSEDOOR(pCmd, pnum);
2620 case CMD_OPERATEOBJ:
2621 return On_OPERATEOBJ(pCmd, pnum);
2622 case CMD_PLROPOBJ:
2623 return On_PLROPOBJ(pCmd, pnum);
2624 case CMD_BREAKOBJ:
2625 return On_BREAKOBJ(pCmd, pnum);
2626 case CMD_CHANGEPLRITEMS:
2627 return On_CHANGEPLRITEMS(pCmd, pnum);
2628 case CMD_DELPLRITEMS:
2629 return On_DELPLRITEMS(pCmd, pnum);
2630 case CMD_PLRLEVEL:
2631 return On_PLRLEVEL(pCmd, pnum);
2632 case CMD_DROPITEM:
2633 return On_DROPITEM(pCmd, pnum);
2634 case CMD_ACK_PLRINFO:
2635 return On_ACK_PLRINFO(pCmd, pnum);
2636 case CMD_SEND_PLRINFO:
2637 return On_SEND_PLRINFO(pCmd, pnum);
2638 case CMD_PLAYER_JOINLEVEL:
2639 return On_PLAYER_JOINLEVEL(pCmd, pnum);
2640 case CMD_ACTIVATEPORTAL:
2641 return On_ACTIVATEPORTAL(pCmd, pnum);
2642 case CMD_DEACTIVATEPORTAL:
2643 return On_DEACTIVATEPORTAL(pCmd, pnum);
2644 case CMD_RETOWN:
2645 return On_RETOWN(pCmd, pnum);
2646 case CMD_SETSTR:
2647 return On_SETSTR(pCmd, pnum);
2648 case CMD_SETMAG:
2649 return On_SETMAG(pCmd, pnum);
2650 case CMD_SETDEX:
2651 return On_SETDEX(pCmd, pnum);
2652 case CMD_SETVIT:
2653 return On_SETVIT(pCmd, pnum);
2654 case CMD_STRING:
2655 return On_STRING(pCmd, pnum);
2656 case CMD_SYNCQUEST:
2657 return On_SYNCQUEST(pCmd, pnum);
2658 case CMD_ENDSHIELD:
2659 return On_ENDSHIELD(pCmd, pnum);
2660 case CMD_CHEAT_EXPERIENCE:
2661 return On_CHEAT_EXPERIENCE(pCmd, pnum);
2662 case CMD_CHEAT_SPELL_LEVEL:
2663 return On_CHEAT_SPELL_LEVEL(pCmd, pnum);
2664 case CMD_NOVA:
2665 return On_NOVA(pCmd, pnum);
2666 case CMD_SETSHIELD:
2667 return On_SETSHIELD(pCmd, pnum);
2668 case CMD_REMSHIELD:
2669 return On_REMSHIELD(pCmd, pnum);
2670 case CMD_REFLECT:
2671 return On_REFLECT(pCmd, pnum);
2672 case CMD_NAKRUL:
2673 return On_NAKRUL(pCmd, pnum);
2674 case CMD_OPENHIVE:
2675 return On_OPENHIVE(pCmd, pnum);
2676 case CMD_OPENCRYPT:
2677 return On_OPENCRYPT(pCmd, pnum);
2678 }
2679
2680 if (pCmd->bCmd < CMD_DLEVEL_0 || pCmd->bCmd > CMD_DLEVEL_END) {
2681 SNetDropPlayer(pnum, LEAVE_DROP);
2682 return 0;
2683 }
2684
2685 return On_DLEVEL(pnum, pCmd);
2686 }
2687
2688 DEVILUTION_END_NAMESPACE
2689