convert line ends
[canaan.git] / prj / cam / src / shock / shkinv.cpp
blob27133be5073a1796c30dea8148055d62ae142338
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 // $Header: r:/t2repos/thief2/src/shock/shkinv.cpp,v 1.108 1999/11/19 14:57:42 adurant Exp $
8 #include <2d.h>
9 #include <res.h>
10 #include <mprintf.h>
12 extern "C" {
13 #include <event.h>
14 #include <slab.h>
15 #include <cursors.h>
18 #include <resapi.h>
19 #include <config.h>
21 #include <objsys.h>
22 #include <osysbase.h>
23 #include <rendprop.h>
24 #include <schbase.h>
25 #include <schema.h>
26 #include <scrnmode.h>
27 #include <scrptsrv.h>
29 #include <dlist.h>
30 #include <dlisttem.h>
32 #include <editor.h>
33 #include <guistyle.h>
34 #include <command.h>
35 #include <frobctrl.h>
36 #include <playrobj.h>
37 #include <prjctile.h>
38 #include <simtime.h>
39 #include <contain.h>
40 #include <combprop.h>
41 #include <physapi.h>
43 #include <keydefs.h>
45 #include <shkprop.h>
46 #include <shkinv.h>
47 #include <shkincst.h>
48 #include <shkiface.h>
49 #include <shkovrly.h>
50 #include <shkovcst.h>
51 #include <shkfsys.h>
52 #include <shkplayr.h>
53 #include <shkplcst.h>
54 #include <shkutils.h>
55 #include <shkgame.h>
56 #include <shkinvpr.h>
57 #include <shkcurm.h>
58 #include <shklooko.h>
59 #include <shkcyber.h>
60 //#include <shkgun.h>
61 #include <gunprop.h>
62 //#include <gunbase.h>
63 #include <shkscapi.h>
64 #include <shktrcst.h>
65 #include <shkarmpr.h>
66 #include <shkpsapi.h>
67 #include <shkifstr.h>
69 // ui library not C++ ized properly yet
70 extern "C" {
71 #include <event.h>
72 #include <gadbox.h>
73 #include <gadblist.h>
74 #include <gadbutt.h>
77 // Must be last header
78 #include <dbmem.h>
80 IRes *gHndInv = NULL;
81 static IRes *gBlockHnd = NULL;
83 static eContainType gLastLoc;
85 #define INV_ICON_X (4)
86 #define INV_ICON_Y (17)
87 #define INV_X 2
88 //#define INV_Y 304
89 #define INV_Y 0
90 Rect inv_icon_rect = { {INV_ICON_X, INV_ICON_Y}, {INV_ICON_X + 523,INV_ICON_Y + 98} };
93 static Rect close_rect = {{5,10},{5 + 20, 10 + 21}};
94 static LGadButton close_button;
95 static DrawElement close_elem;
96 static IRes *close_handles[2];
97 static grs_bitmap *close_bitmaps[4];
100 // Shock inventory system stuff
102 ObjID inv_array[MAX_INV_ITEMS];
103 static Rect inv_rect = {{INV_X,INV_Y},{INV_X + 636, INV_Y + 121}};
104 //Point player_inv_dims = {INV_COLUMNS,INV_ROWS};
105 Point gPlayerMaxInv = {15,3};
107 bool InvCheckSpace(Point space, ObjID obj, int loc);
108 BOOL ShockInvPlayerContainsListener(eContainsEvent event, ObjID container, ObjID containee, eContainType ctype, ContainCBData);
110 grs_canvas gInvCanvas;
111 grs_bitmap *gInvBitmap;
112 BOOL gInvChanged;
114 //--------------------------------------------------------------------------------------
115 void ShockInvClear(void)
117 int i;
118 //if (shock_cursor_mode == SCM_NORMAL)
119 //ShockInvLoadCursor(OBJ_NULL);
120 for (i=0;i < MAX_INV_ITEMS; i++)
121 inv_array[i] = OBJ_NULL;
123 //--------------------------------------------------------------------------------------
124 // reassembles inv_array from containment links to the player
125 void ShockInvReset(void)
127 if (PlayerObjectExists())
129 ShockInvComputeObjArray(PlayerObject(), inv_array);
130 ShockInvRefresh();
133 //--------------------------------------------------------------------------------------
134 void ShockInvInit(int which)
137 gHndInv = LoadPCX("invback");
138 gBlockHnd = LoadPCX("block");
141 int i;
142 close_handles[0] = LoadPCX("CloseOff");
143 close_handles[1] = LoadPCX("CloseOn");
144 close_bitmaps[0] = (grs_bitmap *) close_handles[0]->Lock();
145 close_bitmaps[1] = (grs_bitmap *) close_handles[1]->Lock();
146 for (i = 2; i < 4; i++)
148 close_bitmaps[i] = close_bitmaps[0];
152 ShockInvClear();
154 short w,h;
155 Rect use_rect;
156 sScrnMode smode;
157 ScrnModeGet(&smode);
158 w = RectWidth(&inv_rect);
159 h = RectHeight(&inv_rect);
160 use_rect.ul.x = (smode.w - w) / 2;
161 use_rect.ul.y = inv_rect.ul.y;
162 use_rect.lr.x = use_rect.ul.x + w;
163 use_rect.lr.y = use_rect.ul.y + h;
164 //mprintf("use_rect = %d,%d %d,%d\n",use_rect.ul.x,use_rect.ul.y,use_rect.lr.x,use_rect.lr.y);
165 ShockOverlaySetRect(which,use_rect);
167 ShockInvReset();
169 //grs_bitmap *bmp = (grs_bitmap *) gHndInv->Lock();
170 gInvBitmap = gr_alloc_bitmap(BMT_FLAT16, 0, w, h); // BMF_TRANS
171 //gInvBitmap->align = bmp->align;
172 gr_make_canvas(gInvBitmap, &gInvCanvas);
174 //gHndInv->Unlock();
176 //--------------------------------------------------------------------------------------
177 void ShockInvTerm(void)
179 SafeFreeHnd(&gHndInv);
180 SafeFreeHnd(&gBlockHnd);
182 gr_free(gInvBitmap);
184 close_handles[0]->Unlock();
185 close_handles[1]->Unlock();
186 SafeFreeHnd(&close_handles[0]);
187 SafeFreeHnd(&close_handles[1]);
191 //--------------------------------------------------------------------------------------
192 void ShockInvListenInit()
194 AutoAppIPtr(ContainSys);
195 pContainSys->Listen(gPlayerObj,ShockInvPlayerContainsListener,NULL);
198 //--------------------------------------------------------------------------------------
199 #define ANIM_DUR 250.0F
201 static Rect equip_rects[kEquipMax] = {
202 {{529,16},{562,116}}, // kEquipWeapon
203 {{-1,-1}, {-1,-1}}, // kEquipWeaponAlt
204 {{563,16},{632,83}}, // kEquipArmor
205 {{564,84},{596,117}}, // kEquipSpecial
206 {{599,84},{632,117}}, // kEquipSpecial2
209 void ShockInvDrawCore(void)
211 Point size, drawloc, drawpt;
212 Point mpt,rawpt;
213 Rect r2 = ShockOverlayGetRect(kOverlayInv);
214 Rect r;
215 tSimTime currTime = GetSimTime();
216 ObjID o;
217 int i,dx,dy;
219 r.ul.x = 0;
220 r.ul.y = 0;
221 r.lr.x = RectWidth(&r2);
222 r.lr.y = RectHeight(&r2);
224 AutoAppIPtr(ShockPlayer);
226 size = ContainDimsGetSize(PlayerObject());
227 drawloc.x = r.ul.x + INV_ICON_X;
228 drawloc.y = r.ul.y + INV_ICON_Y;
230 drawpt = r.ul;
232 DrawByHandle(gHndInv,drawpt);
233 //drawloc.y = drawloc.y + (drawpt.y - inv_rect.ul.y);
234 ShockInvDrawObjArray(size, gPlayerMaxInv, inv_array, drawloc);
236 //LGadDrawBox(VB(&close_button),NULL);
238 mouse_get_xy(&rawpt.x,&rawpt.y);
239 mpt.x = rawpt.x - r2.ul.x;
240 mpt.y = rawpt.y - r2.ul.y;
242 // look for mouseover in-inv objects
243 if (RectTestPt(&r2,rawpt))
245 o = ShockInvFindObject(mpt);
246 if (o != OBJ_NULL)
248 ShockInterfaceMouseOver(o);
249 g_ifaceFocusObj = o;
254 // draw the quickbind overlay
255 for (i=0; i < MAX_BIND; i++)
257 int loc;
258 char temp[128];
259 int x,y;
260 int dx, dy;
261 loc = ShockBindVal(i);
262 if ((loc != -1) && (loc < BIND_PSIBASE))
264 x = loc % size.x;
265 y = loc / size.x;
266 sprintf(temp,"F%d",i+1);
267 dx = r.ul.x + INV_ICON_X + (x * INV_ICON_WIDTH);
268 dy = r.ul.y + INV_ICON_Y + (y * INV_ICON_HEIGHT);
269 gr_font_string(gShockFont, temp, dx, dy);
274 // draw equipped items
275 ObjID player = PlayerObject();
277 for (i=0; i <= kEquipSpecial2; i++)
279 // only one hand of weapons these days
280 if (i == kEquipWeaponAlt)
281 continue;
283 if (i == kEquipSpecial2)
285 if (!pShockPlayer->HasTrait(player,kTraitCybernetic))
287 drawpt = equip_rects[i].ul;
288 drawpt.x += r.ul.x;
289 drawpt.y += 1 + r.ul.y;
290 DrawByHandle(gBlockHnd, drawpt);
291 continue;
295 o = pShockPlayer->GetEquip(player, (ePlayerEquip)i);
297 if (RectTestPt(&equip_rects[i],mpt))
299 ShockInterfaceMouseOver(o);
300 g_ifaceFocusObj = o;
302 if (o != OBJ_NULL)
304 dx = r.ul.x + equip_rects[i].ul.x + 1;
305 dy = r.ul.y + equip_rects[i].ul.y + 1;
306 ShockInvObjDraw(o,dx,dy);
308 if (i == kEquipArmor)
310 // draw in some stats for effectiveness of armor
311 int j;
312 char format[128], temp[128];
313 sArmor *pArmor;
314 int w,h;
315 float val = 0;
316 dy = r.ul.y + equip_rects[i].ul.y + 14;
317 for (j=0; j < 3; j++)
319 ArmorGet(o,&pArmor);
320 switch (j)
322 case 0: val = pArmor->m_combat; break;
323 case 1: val = pArmor->m_radiation; break;
324 case 2: val = pArmor->m_toxic; break;
326 if (val == 0)
327 continue;
329 ShockStringFetch(format,sizeof(format),"Armor","misc",j+1);
330 sprintf(temp,format,val);
331 w = gr_font_string_width(gShockFont,temp);
332 h = gr_font_string_height(gShockFont,temp);
333 dx = r.ul.x + equip_rects[i].ul.x + ((RectWidth(&equip_rects[i]) - w) / 2);
334 gr_font_string(gShockFont,temp,dx,dy);
335 dy = dy + h + 3;
343 //--------------------------------------------------------------------------------------
344 void ShockInvDraw(void)
346 Rect r = ShockOverlayGetRect(kOverlayInv);
347 if (gInvChanged)
349 gr_push_canvas(&gInvCanvas);
350 ShockInvDrawCore();
351 gr_pop_canvas();
352 gInvChanged = FALSE;
354 else
356 // determine what is under the mouse
357 Point rawpt, mpt;
358 int i;
359 ObjID o = OBJ_NULL;
360 AutoAppIPtr(ShockPlayer);
362 mouse_get_xy(&rawpt.x,&rawpt.y);
363 mpt.x = rawpt.x - r.ul.x;
364 mpt.y = rawpt.y - r.ul.y;
366 if ((shock_cursor_mode == SCM_DRAGOBJ) && (gLastLoc != ECONTAIN_NULL))
368 int slot;
369 Point dims;
370 dims = ContainDimsGetSize(PlayerObject());
371 slot = ShockInvFindObjSlot(dims,rawpt,drag_obj);
372 if (slot != gLastLoc)
373 gLastLoc = ECONTAIN_NULL;
376 // look for mouseover in-inv objects
377 if (RectTestPt(&r,rawpt))
379 o = ShockInvFindObject(mpt);
382 BOOL inrect = FALSE;
383 for (i=0; (o == OBJ_NULL) && (i <= kEquipSpecial2); i++)
385 // only one hand of weapons these days
386 if (i == kEquipWeaponAlt)
387 continue;
389 if (RectTestPt(&equip_rects[i],mpt))
391 inrect = TRUE;
392 o = pShockPlayer->GetEquip(PlayerObject(), (ePlayerEquip)i);
393 break;
397 if (o != OBJ_NULL)
399 ShockInterfaceMouseOver(o);
400 g_ifaceFocusObj = o;
402 else if (inrect && (i <= kEquipSpecial2))
404 if ((i != kEquipSpecial2) || pShockPlayer->HasTrait(PlayerObject(),kTraitCybernetic))
405 ShockStringFetch(gHelpString,sizeof(gHelpString),"MouseHelpInv","misc",i);
408 gr_bitmap(gInvBitmap, r.ul.x, r.ul.y);
410 //--------------------------------------------------------------------------------------
411 void ShockInvObjDraw(ObjID o, int dx, int dy)
413 Label *lp;
414 IRes *hnd;
415 grs_bitmap *bmp;
416 char temp[255];
418 // get the right bitmap
419 if (ObjGetObjIcon(o,&lp))
421 // find the bitmap
422 hnd = LoadPCX(lp->text,"objicon\\");//);
423 if (hnd != NULL)
425 // draw it!
426 bmp = (grs_bitmap *) hnd->Lock();
427 gr_bitmap(bmp, dx, dy);
428 hnd->Unlock();
430 // cleanup
431 SafeFreeHnd(&hnd);
434 if (ShockObjGetQuantity(o,temp))
436 //w = gr_font_string_width(gShockFont,temp);
437 //gr_set_fcolor(gShockTextColor);
438 gr_font_string(gShockFont, temp, dx + 3 , dy + 3);
442 //--------------------------------------------------------------------------------------
443 BOOL ShockObjGetQuantity(ObjID o, char *temp)
445 // stack count
446 int drawquan = 0; // from the book of draw'quan
447 int quan = 0;
449 if (IProperty_IsRelevant(gStackCountProp,o))
451 gStackCountProp->Get(o,&quan);
452 drawquan = 1;
454 // ammo overlay on weapons
455 else if (ObjHasGunState(o)) // IsGun(o))
457 int wpntype;
458 g_pWeaponTypeProperty->Get(o,&wpntype);
460 if (wpntype !=kWeaponPsiAmp)
462 quan = GunStateGetAmmo(o);
463 drawquan = 1;
466 // energy overlay
467 else if (gPropEnergy->IsRelevant(o))
469 float energy;
470 gPropEnergy->Get(o, &energy);
471 quan = (int)energy;
472 drawquan = 2;
475 if (drawquan)
477 switch (drawquan)
479 case 2:
480 sprintf(temp,"%d^",quan);
481 break;
482 default:
483 sprintf(temp,"%d",quan);
484 break;
488 return(drawquan > 0);
490 //--------------------------------------------------------------------------------------
491 void ShockInvDrawObjArray(Point dims, Point maxdims, ObjID *objarr, Point startloc)
493 //Label *lp;
494 int x,y,dx,dy;
495 int c = 0;
496 ObjID o;
497 int i,j,w,h;
498 bool *drawn;
500 drawn = (bool *)Malloc(sizeof(bool) * dims.x * dims.y);
501 for (i=0; i < dims.x * dims.y; i++)
502 drawn[i] = FALSE;
504 for (y=0; y < maxdims.y; y++)
506 for (x=0; x < maxdims.x; x++)
508 dx = startloc.x + (INV_ICON_WIDTH * x);
509 dy = startloc.y + (INV_ICON_HEIGHT * y);
511 // draw in any "unavailable" blocks
512 if ((y >= dims.y) || (x >= dims.x))
514 Point drawpt;
515 drawpt.x = dx;
516 drawpt.y = dy;
517 DrawByHandle(gBlockHnd, drawpt);
518 continue;
521 // okay, proceed along normally
522 o = objarr[c];
524 // nothing to draw if empty, or already drawn previously
525 if ((o == OBJ_NULL) || drawn[c])
527 c++;
528 continue;
530 ShockInvObjDraw(o,dx,dy);
532 // mark it and all of its slots as drawn
533 w = InvDimsGetWidth(o);
534 h = InvDimsGetHeight(o);
535 for (i = x; i < x + w; i++)
537 for (j = y; j < y + h; j++)
539 int loc = i + (dims.x * j);
540 if (loc < dims.x * dims.y)
541 drawn[loc] = TRUE;
542 else
543 Warning(("Trying to draw obj %d (%d x %d) at %d, %d!\n",o,w,h,x,y));
547 // move on to next obj
548 c++;
552 Free(drawn);
554 //--------------------------------------------------------------------------------------
555 // For the user-interface level, a request to put the object at this location in a container
556 bool SetInvObj(ObjID container, int x, int y, ObjID obj)
558 Point dims;
559 dims = ContainDimsGetSize(container);
560 int ul = (y * dims.x) + x;
561 return(SetInvObj(container, ul,obj));
563 //--------------------------------------------------------------------------------------
564 // For the user-interface level, a request to put the object at this location in a container
565 bool SetInvObj(ObjID container, int ul, int obj)
567 int x,y;
568 int w,h;
569 int i;
570 Point dims;
571 ObjID prevobj = OBJ_NULL;
572 int x1,y1;
573 ObjID *objarr;
575 dims = ContainDimsGetSize(container);
576 x = ul % dims.x;
577 y = ul / dims.x;
579 if (!InvCheckSpace(dims, obj, ul))
581 Warning(("Obj %d does not fit at %d,%d (%d) !\n",obj,x,y,ul));
582 return(FALSE);
585 w = InvDimsGetWidth(obj);
586 h = InvDimsGetHeight(obj);
587 objarr = (ObjID *)Malloc(sizeof(ObjID) * (dims.x * dims.y));
588 ShockInvComputeObjArray(container,objarr);
590 // find objects "underneath" this location
591 AutoAppIPtr(ContainSys);
592 bool keepgoing = TRUE;
593 for (x1 = x; keepgoing && (x1 < x + w); x1++)
595 for (y1 = y; keepgoing && (y1 < y + h); y1++)
597 i = (y1 * dims.x) + x1;
598 //mprintf("analyzing %d at loc %d\n",objarr[i],i);
599 if (objarr[i] != OBJ_NULL)
601 bool remobj = FALSE;
602 // check for combinability
603 HRESULT res = pContainSys->CombineTry(objarr[i], obj, i);
604 if (res == S_OK)
606 // okay, we've merged in our object so we're basically done
607 ShockInvLoadCursor(OBJ_NULL);
608 Free(objarr);
609 return(TRUE);
611 // no combine...
612 // do we already have a cursor swap candidate? if not, make this the one
613 // if so, then too bad we can't resolve this case
614 if (prevobj == OBJ_NULL)
616 prevobj = objarr[i];
618 else
620 if (prevobj != objarr[i])
622 prevobj = OBJ_NULL;
623 keepgoing = FALSE;
630 if (keepgoing) // ie, we didn't abort, so put this obj in the inventory
632 ShockInvLoadCursor(OBJ_NULL);
633 pContainSys->Add(container, obj, ul, CTF_NONE);
637 //mprintf("prevobj is %d\n",prevobj);
638 if (prevobj != OBJ_NULL)
640 // remove it from the inventory
641 pContainSys->Remove(container,prevobj);
642 ShockInvLoadCursor(prevobj);
645 Free(objarr);
646 return(TRUE);
648 //--------------------------------------------------------------------------------------
649 // do the simple geometry to find what slot is being clicked on, given objid on the cursor
650 int ShockInvFindObjSlot(Point dims, Point mpos, ObjID objid)
652 if (!ShockOverlayCheck(kOverlayInv))
653 return(-1);
654 return(ShockInvFindObjSlotPos(dims,mpos,&inv_icon_rect,objid));
657 //--------------------------------------------------------------------------------------
658 // same as above, but more general
659 int ShockInvFindObjSlotPos(Point dims, Point mpos, Rect *pRect, ObjID objid)
661 int x,y;
662 Point offset;
664 //mprintf("mpos = %d, %d\n",mpos.x,mpos.y);
665 if (RectTestPt(pRect, mpos))
667 if (objid == OBJ_NULL)
669 offset.x = 0;
670 offset.y = 0;
672 else
674 // This is kind of ugly. An attempt to deal with issues of mapping the hotspot
675 // of the cursor to the upper left objslot of where it wants to go.
676 int w,h;
677 w = InvDimsGetWidth(objid);
678 h = InvDimsGetHeight(objid);
679 offset.x = (((float)w / 2) - 0.5F) * INV_ICON_WIDTH;
680 offset.y = (((float)h / 2) - 0.5F) * INV_ICON_HEIGHT;
683 x = (mpos.x - offset.x - pRect->ul.x) / INV_ICON_WIDTH;
684 y = (mpos.y - offset.y - pRect->ul.y) / INV_ICON_HEIGHT;
685 if ((x >= dims.x) || (y >= dims.y))
686 return(-1);
687 else
688 return ((y * dims.x) + x);
690 return(-1);
692 //--------------------------------------------------------------------------------------
693 ObjID ShockInvFindObject(int slot)
695 return (inv_array[slot]);
697 //--------------------------------------------------------------------------------------
698 ObjID ShockInvFindObject(Point mpos)
700 int slot;
701 ObjID o;
702 Point dims;
703 dims = ContainDimsGetSize(PlayerObject());
705 if (RectTestPt(&inv_icon_rect, mpos)) /// || RectTestPt(&gunslot_rect, mpos))
707 slot = ShockInvFindObjSlot(dims, mpos);
708 if (slot == -1)
709 o = OBJ_NULL;
710 else
711 o = inv_array[slot];
713 else
714 o = OBJ_NULL;
715 return(o);
717 //--------------------------------------------------------------------------------------
718 bool ShockInvLoadCursor(int o)
720 Label *lp;
721 IRes *hnd;
723 // no effect
725 if (!shock_mouse)
727 if (o != OBJ_NULL)
729 Warning(("ShockInvLoadCursor: not in cursor mode!\n"));
730 return(FALSE);
732 else
733 return(TRUE);
737 //mprintf("loading cursor with obj %d\n",o);
739 if (o == OBJ_NULL)
741 // clear drag
742 ClearCursor();
743 return(TRUE);
746 if (ObjGetObjIcon(o, &lp) && (shock_cursor_mode == SCM_NORMAL))
748 hnd = LoadPCX(lp->text,"objicon\\");
749 if (SetCursorByHandle(hnd))
751 drag_obj = o;
752 shock_cursor_mode = SCM_DRAGOBJ;
753 SafeFreeHnd(&hnd);
754 return(TRUE);
757 return(FALSE);
760 //--------------------------------------------------------------------------------------
761 static int gThrowAudioHnd = -1; // = SFX_NO_HND;
762 static void SchemaDoneCallback(int /*hSchema*/, ObjID /*schemaID*/, void* /*pData*/)
764 gThrowAudioHnd = -1;
766 //--------------------------------------------------------------------------------------
767 // put an object in the first open slot in the inventory
768 bool ShockInvAddObj(ObjID container, ObjID obj)
770 AutoAppIPtr(ContainSys);
771 HRESULT result;
772 Point dims;
773 int loc;
774 ObjID *arr;
775 BOOL space;
777 // Don't do anything if it's already in the inventory; this can
778 // cause duplicate links, which wreak merry hell on networking.
779 if (pContainSys->Contains(container, obj))
780 return(TRUE);
782 dims = ContainDimsGetSize(container);
783 arr = (ObjID *)Malloc(sizeof(ObjID) * dims.x * dims.y);
784 ShockInvComputeObjArray(container,arr);
785 space =ShockInvFindSpace(arr, dims, obj, &loc);
786 Free(arr);
788 AutoAppIPtr(ShockPlayer);
790 // if we are armor, and armor equip slot is free, then wear it
791 if (ObjHasArmor(obj) && (pShockPlayer->GetEquip(container,kEquipArmor) == OBJ_NULL))
793 BOOL equipped;
794 equipped = pShockPlayer->Equip(container,kEquipArmor,obj,FALSE);
795 if (equipped)
796 return(TRUE);
799 // okay, lets just put it the everyday joe inventory
800 if (!space)
802 // first, check for autocombine if we are auto-adding
803 if (!pContainSys->CanCombineContainer(PlayerObject(), obj, -1))
805 // no space, so chuck object back into world
806 ThrowObj(obj, PlayerObject()); // maybe should be from container obj?
807 // this line removed since ThrowObj is guaranteed to set the cursor to OBJ_NULL
808 // if it is the cursor obj anyways
809 //ShockInvLoadCursor(OBJ_NULL);
811 // play an error SFX too
812 if (gThrowAudioHnd == -1)
814 sSchemaCallParams schParams;
815 memset (&schParams, 0, sizeof (schParams));;
816 schParams.flags = SCH_SET_CALLBACK;
817 schParams.sourceID = OBJ_NULL;
818 schParams.callback = SchemaDoneCallback;
820 gThrowAudioHnd = SchemaPlay((Label *)"bb11",&schParams);
822 //gThrowAudioHnd = SchemaPlay((Label *)"bb11",NULL);
823 return(FALSE);
827 result = pContainSys->Add(container,obj,loc,CTF_COMBINE);
828 if (result == S_OK)
830 if (drag_obj == obj)
831 ShockInvLoadCursor(OBJ_NULL);
832 return(TRUE);
834 else
835 return(FALSE);
837 //--------------------------------------------------------------------------------------
838 bool ShockInvFindSpace(ObjID *arr, Point dims, ObjID obj, int *slot)
840 int i;
841 int x,y,x1,y1;
842 int w,h;
844 #ifdef PLAYTEST
845 if (dims.x == 0)
847 Warning(("Object %d does not have a valid container dimension!\n",obj));
848 return(FALSE);
850 #endif
852 for (x = 0; x < dims.x ; x++)
854 for (y=0; y < dims.y; y++)
856 i = x + (y * dims.x);
857 if (arr[i] == OBJ_NULL)
859 // is there enough room here?
860 bool space = TRUE;
861 w = InvDimsGetWidth(obj);
862 h = InvDimsGetHeight(obj);
863 // are we too close to the edges?
864 if ((x + w > dims.x) || (y + h > dims.y))
865 space = FALSE;
866 // now check for enough clear slots
867 for (x1 = x; space && (x1 < x + w); x1++)
869 for (y1 = y; space && (y1 < y + h); y1++)
871 if (arr[x1 + (y1 * dims.x)] != OBJ_NULL)
872 space = FALSE;
875 if (space)
877 *slot = i;
878 return(TRUE);
883 // no matches found
884 return(FALSE);
886 //--------------------------------------------------------------------------------------
887 bool ShockInvPayNanites(int quan)
889 AutoAppIPtr(ContainSys);
890 AutoAppIPtr(ObjectSystem);
891 HRESULT res;
893 ObjID arch = pObjectSystem->GetObjectNamed("Nanites");
894 res = pContainSys->CombineAdd(PlayerObject(),arch,-quan);
895 if (res == S_OK)
896 return(TRUE);
897 else
898 return(FALSE);
900 //--------------------------------------------------------------------------------------
901 int ShockInvNaniteTotal(void)
903 int retval;
904 AutoAppIPtr(ContainSys);
905 AutoAppIPtr(ObjectSystem);
906 ObjID arch = pObjectSystem->GetObjectNamed("Nanites");
907 retval = pContainSys->CombineCount(PlayerObject(),arch);
908 return(retval);
910 //--------------------------------------------------------------------------------------
912 static bool close_cb(short action, void* data, LGadBox* vb)
914 if (action == BUTTONGADG_LCLICK) // || (action == BUTTONGADG_RCLICK))
916 uiDefer(DeferOverlayClose,(void *)kOverlayInv);
917 //SchemaPlay((Label *)"subpanel_cl",NULL);
919 return(TRUE);
922 //--------------------------------------------------------------------------------------
923 static void BuildInterfaceButtons(void)
926 Rect r;
927 r = ShockOverlayGetRect(kOverlayInv);
929 // set up the continue button
930 close_elem.draw_type = DRAWTYPE_BITMAPOFFSET;
931 close_elem.draw_data = close_bitmaps;
932 close_elem.draw_data2 = (void *)4; // should be 2 but hackery required
934 LGadCreateButtonArgs(&close_button, LGadCurrentRoot(), close_rect.ul.x + r.ul.x, close_rect.ul.y + r.ul.y,
935 RectWidth(&close_rect), RectHeight(&close_rect), &close_elem, close_cb, 0);
939 //--------------------------------------------------------------------------------------
940 static void DestroyInterfaceButtons(void)
942 //LGadDestroyBox(VB(&close_button),FALSE);
944 //--------------------------------------------------------------------------------------
945 void ShockInvStateChange(int which)
947 gInvChanged = TRUE;
948 if (ShockOverlayCheck(which))
949 BuildInterfaceButtons(); // just got put up
950 else
951 DestroyInterfaceButtons(); // just got taken down
953 //--------------------------------------------------------------------------------------
954 // Check for transparency in the source art
955 //--------------------------------------------------------------------------------------
956 bool ShockInvCheckTransp(Point pt)
958 // for now, always return false so we don't get tricked by the transparency
959 // in the interlacing.
960 return(FALSE);
962 bool retval = FALSE;
963 Point p;
964 Rect r;
965 r = ShockOverlayGetRect(kOverlayInv);
966 p.x = pt.x - r.ul.x;
967 p.y = pt.y - r.ul.y;
968 int pix;
969 pix = HandleGetPix(gHndInv,p);
971 if (pix == 0)
972 retval = TRUE;
973 //mprintf("SICT: %d (%d)\n",retval,pix);
974 return(retval);
977 //--------------------------------------------------------------------------------------
978 // Basic interface handling.
979 //--------------------------------------------------------------------------------------
980 //EXTERN int hack_for_kbd_state(void);
981 //#define CTRL_STATES (KBM_LCTRL|KBM_RCTRL)
982 bool ShockInvHandleMouse(Point pos)
985 ObjID o;
986 //bool retval = TRUE;
988 o = ShockInvFindObject(pos);
989 mprintf("SIHM = %d, %d, obj = %d\n",pos.x,pos.y,o);
991 switch (shock_cursor_mode)
993 case SCM_PSI:
994 if (o != OBJ_NULL)
996 AutoAppIPtr(PlayerPsi);
997 pPlayerPsi->PsiTarget(o);
999 ClearCursor();
1000 break;
1004 return(TRUE);
1007 //--------------------------------------------------------------------------------------
1008 bool ShockInvDoubleClick(Point pos)
1010 ObjID o;
1012 if (shock_cursor_mode == SCM_NORMAL)
1014 gInvChanged = TRUE;
1016 // mprintf("double click!\n");
1017 o = ShockInvFindObject(pos);
1018 if (o == OBJ_NULL)
1020 int i;
1021 AutoAppIPtr(ShockPlayer);
1022 for (i=0; i < kEquipMax; i++)
1024 if (RectTestPt(&equip_rects[i],pos))
1026 ePlayerEquip slot = (ePlayerEquip)i;
1028 o = pShockPlayer->GetEquip(PlayerObject(), slot);
1032 if (o != OBJ_NULL)
1034 // direct in-inv usage
1035 frobInvSelectObj = o;
1036 ShockDoFrob(TRUE);
1037 //mprintf("inv frobbing objid %d\n",o);
1040 return(TRUE);
1042 //--------------------------------------------------------------------------------------
1043 void ShockInvTakeMe(ObjID obj)
1045 ShockInvLoadCursor(obj);
1046 AutoAppIPtr(ContainSys);
1047 pContainSys->Remove(PlayerObject(),obj);
1048 SchemaPlay((Label *)"select_item",NULL);
1050 //--------------------------------------------------------------------------------------
1051 // user has down-alt-clicked on a stack
1052 // if it isn't stackable, just put it on the cursor
1053 // if it is stackable, but the increment is the whole stack, put it on the cursor
1054 // otherwise, put on the cursor an increment's worth, and leave the rest in place.
1055 // If leaveEmpty is TRUE, then an empty stack will be left behind if
1056 // all are taken.
1057 void ShockSplitStack(ObjID obj, BOOL leaveEmpty)
1059 if (obj == OBJ_NULL)
1060 return;
1062 AutoAppIPtr(ObjectSystem);
1063 int maxobj,currobj;
1064 maxobj = pObjectSystem->MaxObjID();
1065 currobj = pObjectSystem->ActiveObjects();
1066 if (currobj > maxobj * 9 / 10)
1068 char temp[255];
1069 ShockStringFetch(temp,sizeof(temp),"TooManyObjs","misc");
1070 ShockOverlayAddText(temp,DEFAULT_MSG_TIME);
1071 return;
1074 gInvChanged = TRUE;
1076 int increm = 1;
1077 int num = 0;
1078 gPropStackIncrem->Get(obj,&increm);
1080 // the case where we take all and leave nothing behind
1081 if (!gStackCountProp->Get(obj,&num) || (num <= increm))
1083 if (leaveEmpty)
1085 increm = num;
1086 } else {
1087 // Just take the whole stack
1088 ShockInvTakeMe(obj);
1089 return;
1093 // okay, we are actually splitting
1094 ObjID newobj;
1095 AutoAppIPtr(ContainSys);
1097 // this will create a new object as well
1098 if (leaveEmpty)
1099 newobj = pContainSys->RemoveFromStack(obj, kStackRemoveLeaveEmpty, increm);
1100 else
1101 newobj = pContainSys->RemoveFromStack(obj, 0, increm);
1102 ObjSetHasRefs(newobj,FALSE);
1103 PhysDeregisterModel(newobj);
1105 // put it on our cursor, voila!
1106 ShockInvLoadCursor(newobj);
1108 //--------------------------------------------------------------------------------------
1109 bool ShockInvDragDrop(Point pos, BOOL start)
1111 ObjID o,prevobj;
1112 int i;
1113 ObjID player = PlayerObject();
1114 AutoAppIPtr(ShockPlayer);
1116 gInvChanged = TRUE;
1118 // first off, are we over an equip slot?
1119 for (i=0; i < kEquipMax; i++)
1121 if (RectTestPt(&equip_rects[i],pos))
1123 ePlayerEquip slot = (ePlayerEquip)i;
1125 prevobj = pShockPlayer->GetEquip(player, slot);
1126 switch (shock_cursor_mode)
1128 case SCM_DRAGOBJ:
1130 // don't do anything on downs with something on the cursor
1131 if (start)
1133 prevobj = OBJ_NULL;
1134 break;
1137 BOOL place_item = FALSE;
1138 if (prevobj == OBJ_NULL)
1140 if ((gLastLoc == ECONTAIN_NULL) || (gLastLoc != slot))
1141 place_item = TRUE;
1143 else
1145 // inv-inv tool usage
1146 frobInvSelectObj = prevobj;
1147 ShockDoFrob(FALSE);
1149 if (ShockScriptAllowSwap())
1150 place_item = TRUE;
1152 if (place_item)
1154 if (pShockPlayer->Equip(player, slot,drag_obj,TRUE))
1155 ShockInvLoadCursor(OBJ_NULL);
1156 else
1157 prevobj = OBJ_NULL; // leave the old obj in place
1159 else
1160 prevobj = OBJ_NULL;
1162 break;
1163 case SCM_NORMAL:
1164 if (start)
1166 gLastLoc = slot;
1167 pShockPlayer->Equip(player, slot,OBJ_NULL,TRUE);
1169 else
1170 prevobj = OBJ_NULL;
1171 break;
1172 case SCM_LOOK:
1173 if (!start)
1175 if (prevobj != OBJ_NULL)
1176 ShockLookPopup(prevobj);
1177 ClearCursor();
1178 // leave equipped obj in place
1180 prevobj = OBJ_NULL;
1181 break;
1182 case SCM_PSI:
1183 if (!start)
1185 if (prevobj != OBJ_NULL)
1187 AutoAppIPtr(PlayerPsi);
1188 pPlayerPsi->PsiTarget(prevobj);
1190 ClearCursor();
1191 // leave equipped obj in place
1193 prevobj = OBJ_NULL;
1194 break;
1196 if (prevobj != OBJ_NULL)
1198 // handle combinables
1199 AutoAppIPtr(ContainSys);
1200 // agh, clean this up
1201 if (pContainSys->CombineTry(pShockPlayer->GetEquip(player, slot),prevobj,SHOCKCONTAIN_PDOLLBASE + slot) == S_OK)
1202 ShockInvLoadCursor(OBJ_NULL);
1203 else
1204 ShockInvLoadCursor(prevobj);
1209 // otherwise, do the normal thing
1211 o = ShockInvFindObject(pos);
1213 switch (shock_cursor_mode)
1215 case SCM_DRAGOBJ:
1217 if (!start)
1219 BOOL place_item = FALSE;
1220 int slot;
1221 Point dims;
1222 dims = ContainDimsGetSize(PlayerObject());
1223 slot = ShockInvFindObjSlot(dims,pos,drag_obj);
1224 if (o == OBJ_NULL)
1226 if ((gLastLoc == ECONTAIN_NULL) || (gLastLoc != slot))
1227 place_item = TRUE;
1229 else
1231 // inv-inv tool usage
1232 frobInvSelectObj = o; // since this is the "target" of the tool frob
1233 ShockDoFrob(FALSE);
1234 //mprintf("tool frobbing objid %d with %d\n",o,drag_obj); // shock_cursor_useobj);
1236 if (ShockScriptAllowSwap())
1237 place_item = TRUE;
1239 gLastLoc = ECONTAIN_NULL;
1240 if (place_item)
1242 if (slot != -1)
1244 // make the contains system request
1245 // automagically handles swapping and combining
1246 SchemaPlay((Label *)"place_item", NULL);
1247 SetInvObj(PlayerObject(),slot,drag_obj);
1252 break;
1253 case SCM_NORMAL:
1254 if (o != OBJ_NULL)
1256 if (start)
1258 AutoAppIPtr(ContainSys);
1259 gLastLoc = pContainSys->IsHeld(PlayerObject(),o);
1260 ShockInvTakeMe(o);
1263 break;
1264 case SCM_LOOK:
1265 if ((o != OBJ_NULL) && !start)
1267 ShockLookPopup(o);
1268 ClearCursor();
1270 break;
1271 case SCM_PSI:
1272 if ((o != OBJ_NULL) && !start)
1274 AutoAppIPtr(PlayerPsi);
1275 pPlayerPsi->PsiTarget(o);
1276 ClearCursor();
1278 break;
1279 case SCM_SPLIT:
1280 if (start)
1282 ClearCursor();
1283 if (o != OBJ_NULL)
1284 ShockSplitStack(o, FALSE);
1286 break;
1289 return(TRUE);
1291 //--------------------------------------------------------------------------------------
1292 void ShockInvFillObjPos(ObjID o, ObjID *arr, int ctpos, Point dims)
1294 // assumes object will fit!
1296 // filter out objects that are contained by not in standard object array space
1297 if (ctpos >= SHOCKCONTAIN_PDOLLBASE)
1298 return;
1300 int x,y,w,h;
1301 int x1,y1;
1302 // simple conversion, may become more complex?
1303 x1 = ctpos % dims.x;
1304 y1 = ctpos / dims.x;
1305 w = InvDimsGetWidth(o);
1306 h = InvDimsGetHeight(o);
1307 for (x = x1; x < x1 + w; x++)
1308 for (y = y1; y < y1 + h; y++)
1309 arr[x + (dims.x * y)] = o;
1312 //--------------------------------------------------------------------------------------
1313 void ShockInvComputeObjArray(ObjID o, ObjID *arr)
1315 AutoAppIPtr(ContainSys);
1316 Point dims;
1317 sContainIter *piter;
1318 int i;
1320 if (o == OBJ_NULL)
1321 return;
1323 dims = ContainDimsGetSize(o);
1324 if ((dims.x == 0) || (dims.y == 0))
1326 Warning(("ShockInvComputeObjArray:: dims is zero!\n"));
1327 return;
1329 piter = pContainSys->IterStart(o);
1330 for (i=0; i < dims.x * dims.y; i++)
1331 arr[i] = OBJ_NULL;
1332 while (!piter->finished)
1334 if (piter->type < SHOCKCONTAIN_PDOLLBASE)
1335 ShockInvFillObjPos(piter->containee,arr,piter->type,dims);
1336 pContainSys->IterNext(piter);
1338 pContainSys->IterEnd(piter);
1340 //--------------------------------------------------------------------------------------
1341 static bool InvCheckSpace(Point space, ObjID obj, int loc)
1343 int x,y,w,h;
1344 w = InvDimsGetWidth(obj);
1345 h = InvDimsGetHeight(obj);
1346 x = loc % space.x;
1347 y = loc / space.x;
1349 // okay, double-check that we fit
1350 if ((x + w - 1 >= space.x) || (y + h - 1 >= space.y))
1351 return(FALSE);
1353 return(TRUE);
1355 //--------------------------------------------------------------------------------------
1356 static bool InvCheckSpace(Point space, ObjID obj, int x, int y)
1358 int w,h;
1359 w = InvDimsGetWidth(obj);
1360 h = InvDimsGetHeight(obj);
1362 // okay, double-check that we fit
1363 if ((x + w - 1 >= space.x) || (y + h - 1 >= space.y))
1364 return(FALSE);
1366 return(TRUE);
1368 //--------------------------------------------------------------------------------------
1369 // really only for use by the listener
1370 void InvClearObj(int objid, ObjID *invarr)
1372 // finds all object slots that are equal to objid
1373 int i;
1375 for (i=0; i < MAX_INV_ITEMS; i++)
1377 if (invarr[i] == objid)
1379 invarr[i] = OBJ_NULL;
1383 //--------------------------------------------------------------------------------------
1384 BOOL ShockInvPlayerContainsListener(eContainsEvent event, ObjID container, ObjID containee, eContainType ctype, ContainCBData )
1386 if (container != PlayerObject()) {
1387 // This actually gets called for any containment change, but we
1388 // only care about the player:
1389 return TRUE;
1392 gInvChanged = TRUE;
1394 Point dims;
1395 dims = ContainDimsGetSize(container);
1396 BOOL retval = TRUE;
1397 int loc;
1399 loc = ctype; // simple conversion, eh?
1401 switch (event)
1403 case kContainAdd:
1404 if (loc < SHOCKCONTAIN_PDOLLBASE)
1406 //mprintf("trying to place obj %d at loc %d\n",containee,loc);
1407 if (InvCheckSpace(dims,containee,loc))
1408 ShockInvFillObjPos(containee, inv_array, loc, dims);
1409 else
1410 retval = FALSE;
1412 break;
1414 case kContainRemove:
1416 if (loc >= SHOCKCONTAIN_PDOLLBASE)
1418 AutoAppIPtr(ShockPlayer);
1419 pShockPlayer->Equip(container, (ePlayerEquip)loc,OBJ_NULL);
1422 InvClearObj(containee, inv_array);
1423 break;
1426 return(retval);
1428 //--------------------------------------------------------------------------------------
1429 typedef struct
1431 ObjID obj;
1432 int loc;
1433 } sResizeData;
1435 void ShockInvResize(ObjID obj, sContainDims *olddims, sContainDims *dims)
1437 int newloc;
1438 Point oldpt;
1439 Point invdims;
1440 sContainIter *piter;
1441 AutoAppIPtr(ContainSys);
1443 gInvChanged = TRUE;
1445 // rearrange the inventory values to accomodate the new size,
1446 // while not appearing to move at all.
1448 // note that we have to gather the data in one pass, and set
1449 // the data in a second pass to avoid modifying the data we
1450 // are iterating over.
1451 cSimpleDList<sResizeData> contents;
1453 piter = pContainSys->IterStart(obj);
1454 while (!piter->finished)
1456 sResizeData rsd;
1458 rsd.obj = piter->containee;
1459 rsd.loc = piter->type;
1460 contents.Append(rsd);
1462 pContainSys->IterNext(piter);
1464 pContainSys->IterEnd(piter);
1466 ShockInvClear();
1468 // now that we have assembled a list of data, go poke
1469 // in the new locations for everything
1470 cSimpleDList<ObjID> objlist;
1471 cSimpleDList<sResizeData>::cIter iter;
1472 for (iter = contents.Iter(); !iter.Done(); iter.Next())
1474 sResizeData rsd;
1475 rsd = iter.Value();
1476 if (rsd.loc < SHOCKCONTAIN_PDOLLBASE)
1478 oldpt.x = rsd.loc % olddims->m_width;
1479 oldpt.y = rsd.loc / olddims->m_width;
1481 newloc = (oldpt.y * dims->m_width) + oldpt.x;
1483 // if the object is now in an invalid space, pitch it
1484 invdims.x = dims->m_width;
1485 invdims.y = dims->m_height;
1486 // compare the old location to the new dimensions
1487 if (InvCheckSpace(invdims,rsd.obj, oldpt.x,oldpt.y))
1489 pContainSys->SetContainType(obj,rsd.obj, newloc);
1490 ShockInvFillObjPos(rsd.obj, inv_array, newloc, invdims);
1492 else
1494 // make a list of stuff to try and re-place in the inventory
1495 pContainSys->Remove(obj,rsd.obj);
1496 objlist.Append(rsd.obj);
1501 // note if we have anything on the cursor
1502 ObjID save_obj = drag_obj;
1504 // try to replace the misfits
1505 cSimpleDList<ObjID>::cIter objiter;
1506 for (objiter = objlist.Iter(); !objiter.Done(); objiter.Next())
1508 ObjID o;
1509 o = objiter.Value();
1510 ShockInvAddObj(obj,o);
1513 // restore the cursor if necessary
1514 if (save_obj != OBJ_NULL)
1516 ShockInvLoadCursor(save_obj);
1520 //--------------------------------------------------------------------------------------
1521 void ShockInvDestroyCursorObj(void)
1523 if (drag_obj == OBJ_NULL)
1524 return;
1526 IObjectSystem* pOS = AppGetObj(IObjectSystem);
1527 pOS->Destroy(drag_obj);
1528 SafeRelease(pOS);
1530 ShockInvLoadCursor(OBJ_NULL);
1532 //--------------------------------------------------------------------------------------
1534 int ShockInvQuickbind(void)
1536 Point rawpt, mpt;
1537 Rect r = ShockOverlayGetRect(kOverlayInv);
1538 eContainType retval;
1539 ObjID o;
1541 // look around for an object under the cursor to bind.
1542 mouse_get_xy(&rawpt.x,&rawpt.y);
1543 mpt.x = rawpt.x - r.ul.x;
1544 mpt.y = rawpt.y - r.ul.y;
1545 o = ShockInvFindObject(mpt);
1547 // return its containtype
1548 AutoAppIPtr(ContainSys);
1549 retval = pContainSys->IsHeld(PlayerObject(), o);
1550 if (retval == ECONTAIN_NULL)
1551 return(-1);
1553 return(retval);
1557 void ShockInvRefresh(void)
1559 gInvChanged = TRUE;
1562 //--------------------------------------------------------------------------------------
1563 // the area at the bottom that holds your dedicated inventory slots
1564 //--------------------------------------------------------------------------------------
1565 #define AMMO_X 378
1566 #define AMMO_Y 414
1568 #define BIO_X 2
1569 #define BIO_Y 414
1571 static Rect ticker_rect = {{0,0},{0,0}};
1572 #define BUTTON_RECT(x,y) {{x,y},{x + INV_ICON_WIDTH, y + INV_ICON_HEIGHT}}
1573 Rect fake_rects[4] = {
1574 BUTTON_RECT(BIO_X + 183, BIO_Y + 21),
1575 BUTTON_RECT(BIO_X + 222, BIO_Y + 21),
1576 BUTTON_RECT(AMMO_X + 5, AMMO_Y + 20),
1577 BUTTON_RECT(AMMO_X + 44, AMMO_Y + 20),
1579 //--------------------------------------------------------------------------------------
1580 void ShockTickerInit(int which)
1582 sScrnMode smode;
1583 Rect use_rect;
1585 ScrnModeGet(&smode);
1586 if (smode.w == 640)
1588 use_rect.ul.x = ticker_rect.ul.x;
1589 use_rect.ul.y = ticker_rect.ul.y;
1591 else
1593 use_rect.ul.x = (smode.w - 640);
1594 use_rect.ul.y = (smode.h - 480);
1597 ShockOverlaySetRect(which,use_rect);
1600 //--------------------------------------------------------------------------------------
1601 void ShockTickerTerm(void)
1605 //--------------------------------------------------------------------------------------
1606 void ShockTickerDraw(void)
1608 Rect r = ShockOverlayGetRect(kOverlayTicker);
1609 ObjID o;
1610 int i;
1611 Point mpt; // rawpt,drawpt,
1613 //DrawByHandle(gTickerHnd,r.ul);
1614 AutoAppIPtr(ShockPlayer);
1617 mouse_get_xy(&rawpt.x,&rawpt.y);
1618 mpt.x = rawpt.x - r.ul.x;
1619 mpt.y = rawpt.y - r.ul.y;
1621 mouse_get_xy(&mpt.x,&mpt.y);
1623 for (i=kEquipFakeNanites; i <= kEquipFakeKeys; i++)
1625 o = pShockPlayer->GetEquip(PlayerObject(), (ePlayerEquip)i);
1626 // special case for 2-handed weapons
1627 Rect userect;
1628 Point offset;
1629 if (i >= kEquipFakeLogs)
1631 offset.x = r.ul.x;
1632 offset.y = r.ul.y;
1634 else
1636 offset.x = 0;
1637 offset.y = r.ul.y;
1639 RectOffsettedRect(&fake_rects[i-kEquipFakeNanites], offset, &userect);
1641 if (RectTestPt(&userect,mpt))
1643 ShockInterfaceMouseOver(o);
1644 g_ifaceFocusObj = o;
1646 if (o != OBJ_NULL)
1649 drawpt.x = fake_rects[i - kEquipFakeNanites].ul.x + 1;
1650 if (i >= kEquipFakeLogs)
1651 drawpt.x += r.ul.x;
1652 drawpt.y = r.ul.y + fake_rects[i - kEquipFakeNanites].ul.y + 1;
1654 ShockInvObjDraw(o,userect.ul.x,userect.ul.y); // drawpt.x,drawpt.y);
1658 //--------------------------------------------------------------------------------------
1659 EXTERN bool ShockTickerHandleMouse(Point pos)
1661 return(TRUE);
1663 //--------------------------------------------------------------------------------------
1664 // puts cursor in look-at mode
1665 void ShockSplitCursor(void)
1667 IRes *hnd;
1669 ClearCursor();
1670 shock_cursor_mode = SCM_SPLIT;
1671 //mprintf("SLC!\n");
1672 hnd = LoadPCX("splitcur","iface\\");
1673 SetCursorByHandle(hnd);
1674 SafeFreeHnd(&hnd);
1676 //--------------------------------------------------------------------------------------
1677 sOverlayFunc OverlayInv = {
1678 ShockInvDraw, // draw
1679 ShockInvInit, // init
1680 ShockInvTerm, // term
1681 ShockInvHandleMouse, // mouse
1682 ShockInvDoubleClick, // dclick (really use)
1683 ShockInvDragDrop, // dragdrop
1684 NULL, // key
1685 NULL, // bitmap
1686 "", // upschema
1687 "", // downschema
1688 ShockInvStateChange, // state
1689 ShockInvCheckTransp, // transparency
1690 0, // distance
1691 TRUE, // needmouse
1694 sOverlayFunc OverlayTicker = {
1695 ShockTickerDraw, // draw
1696 ShockTickerInit, // init
1697 ShockTickerTerm, // term
1698 ShockTickerHandleMouse, // mouse
1699 NULL, // dclick (really use)
1700 NULL, // dragdrop
1701 NULL, // key
1702 NULL, // bitmap
1703 "", // upschema
1704 "", // downschema
1705 NULL, // state
1706 NULL, // transparency
1707 0, // distance
1708 FALSE, // needmouse