2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // $Header: r:/t2repos/thief2/src/shock/shkrep.cpp,v 1.42 2000/02/19 13:26:06 toml Exp $
56 // ui library not C++ ized properly yet
63 #include <dbmem.h> // must be last header!
66 ObjID g_repID
= OBJ_NULL
; // ugh, what a hack
68 int gRepSelection
= -1; // which actual object
69 int gRepFocus
= 0; // for simple scroll
70 int gRepFocusMax
; // max valid focus
71 static IRes
*gHndRep
= NULL
;
72 static IRes
*gHndBroken
= NULL
;
73 static IRes
*gHndSelect
= NULL
;
75 static Rect full_rect
= {{LMFD_X
, LMFD_Y
}, {LMFD_X
+ LMFD_W
, LMFD_Y
+ LMFD_H
}};
76 static Rect close_rect
= {{163,8},{163 + 20, 8 + 21}};
78 //static Rect buy_rect = {{156,212},{156 + 17, 212 + 73}};
79 //static Rect up_rect = {{156,152},{156 + 17, 152 + 17}};
80 //static Rect down_rect = {{156,183},{156 + 17, 183 + 17}};
82 #define NUM_REPLICATOR_BOXES 4
84 #define BOX_BUTTON(x,y) {{(x),(y)},{(x)+142,(y)+62}}
86 static Rect obj_rects
[NUM_REPLICATOR_BOXES
] = {
93 static LGadButton close_button
;
94 static DrawElement close_elem
;
95 static IRes
*close_handles
[2];
96 static grs_bitmap
*close_bitmaps
[4];
99 static LGadButton buy_button;
100 static DrawElement buy_elem;
101 static IRes *buy_handles[2];
102 static grs_bitmap *buy_bitmaps[4];
106 static LGadButton up_button;
107 static DrawElement up_elem;
108 static IRes *up_handles[2];
109 static grs_bitmap *up_bitmaps[4];
111 static LGadButton down_button;
112 static DrawElement down_elem;
113 static IRes *down_handles[2];
114 static grs_bitmap *down_bitmaps[4];
117 static int gRepAudioHnd
= -1; // = SFX_NO_HND;
119 //--------------------------------------------------------------------------------------
120 static void DorkBitmaps(grs_bitmap
**bitmaps
, IRes
**handles
)
123 for (i
=0; i
< 2; i
++)
125 bitmaps
[i
] = (grs_bitmap
*)handles
[i
]->Lock();
127 for (i
= 2; i
< 4; i
++)
129 bitmaps
[i
] = bitmaps
[0];
133 //--------------------------------------------------------------------------------------
134 static void ReleaseHandles(IRes
**handles
)
136 handles
[0]->Unlock();
137 handles
[1]->Unlock();
138 SafeFreeHnd(&handles
[0]);
139 SafeFreeHnd(&handles
[1]);
141 //--------------------------------------------------------------------------------------
142 void ShockRepInit(int which
)
144 close_handles
[0] = LoadPCX("CloseOff");
145 close_handles
[1] = LoadPCX("CloseOn");
146 DorkBitmaps(close_bitmaps
, close_handles
);
149 buy_handles[0] = LoadPCX("check0");
150 buy_handles[1] = LoadPCX("check1");
151 DorkBitmaps(buy_bitmaps, buy_handles);
155 up_handles[0] = LoadPCX("up0");
156 up_handles[1] = LoadPCX("up1");
157 DorkBitmaps(up_bitmaps, up_handles);
159 down_handles[0] = LoadPCX("down0");
160 down_handles[1] = LoadPCX("down1");
161 DorkBitmaps(down_bitmaps, down_handles);
164 gHndRep
= LoadPCX("replic");
165 gHndBroken
= LoadPCX("breplic");
166 gHndSelect
= LoadPCX("repsel");
167 SetLeftMFDRect(which
, full_rect
);
170 //--------------------------------------------------------------------------------------
171 void ShockRepTerm(void)
173 SafeFreeHnd(&gHndRep
);
174 SafeFreeHnd(&gHndBroken
);
175 SafeFreeHnd(&gHndSelect
);
176 ReleaseHandles(close_handles
);
177 //ReleaseHandles(buy_handles);
178 //ReleaseHandles(up_handles);
179 //ReleaseHandles(down_handles);
183 //--------------------------------------------------------------------------------------
184 // Get projectile from link
185 ObjID
GetRepMarker(ObjID objID
)
187 ObjID marker
= OBJ_NULL
;
188 AutoAppIPtr(LinkManager
);
189 // @TODO: make this a inheritance query on a trait
190 ILinkQuery
*pQuery
= pLinkManager
->Query(objID
, LINKOBJ_WILDCARD
, g_pReplicatorLinks
->GetID());
201 //--------------------------------------------------------------------------------------
202 static void SchemaDoneCallback(int /*hSchema*/, ObjID
/*schemaID*/, void* /*pData*/)
206 //--------------------------------------------------------------------------------------
208 static void FabricateItem(char *name
, ObjID srcobj
)
211 ObjPos
*pos
, *temp
, pos2
;
212 IObjectSystem
*objsys
;
215 objsys
= AppGetObj(IObjectSystem
);
216 maxobj
= objsys
->MaxObjID();
217 currobj
= objsys
->ActiveObjects();
218 if (currobj
> maxobj
* 9 / 10)
221 ShockStringFetch(temp
,sizeof(temp
),"TooManyObjs","misc");
222 ShockOverlayAddText(temp
,DEFAULT_MSG_TIME
);
226 arch
= objsys
->GetObjectNamed(name
);
227 oid
= objsys
->BeginCreate(arch
,kObjectConcrete
);
228 pos
= ObjPosGet(srcobj
);
230 // get our target location by following the link
231 dest
= GetRepMarker(srcobj
);
232 temp
= ObjPosGet(dest
);
233 memcpy(&pos2
,temp
,sizeof(ObjPos
));
234 // a minor deviation so they don't stack
235 pos2
.loc
.vec
.x
+= (((float)(Rand() % 100)) / 200.0F
) - 0.25F
;
236 pos2
.loc
.vec
.y
+= (((float)(Rand() % 100)) / 200.0F
) - 0.25F
;
239 ObjPosCopyUpdate(oid
,&pos2
);
240 objsys
->EndCreate(oid
);
241 PhysSetModLocation(oid
,&pos2
.loc
.vec
);
243 //PhysRegisterSphere(oid,1,0,0.5F);
244 SFX_Play_Raw(SFX_STATIC
, NULL
, "zot4");
246 // Set up callback which resets our global upon play completion.
247 sSchemaCallParams schParams
;
248 memset (&schParams
, 0, sizeof (schParams
));;
249 schParams
.flags
= SCH_SET_CALLBACK
;
250 schParams
.sourceID
= OBJ_NULL
;
251 schParams
.callback
= SchemaDoneCallback
;
252 // schParams.pData = ; // user data for callback
254 // Halt if an email is already playing.
255 if (gRepAudioHnd
!= -1)
257 SchemaPlayHalt(gRepAudioHnd
);
260 gRepAudioHnd
= SchemaPlay((Label
*)"replicator2e", &schParams
); //NULL);
261 //SFX_Play_Raw(SFX_STATIC, NULL, "replicator2e");
263 //--------------------------------------------------------------------------------------
264 static int RepFindSlot(Point pt
)
269 // find any obj boxes that it hits
270 for (i
=0; i
< NUM_REPLICATOR_BOXES
; i
++)
272 if (RectTestPt(&obj_rects
[i
],pt
))
277 //--------------------------------------------------------------------------------------
278 bool ShockReplicate(int which
)
286 if (g_repID
!= OBJ_NULL
)
288 cost
= RepContentsGetCost(g_repID
,which
);
289 // cost == 0 means no item there
290 total
= ShockInvNaniteTotal();
291 if ((cost
!= 0) && (cost
<= total
))
293 if (ShockInvPayNanites(cost
))
295 RepContentsGetObj(g_repID
,which
,temp
);
296 FabricateItem(temp
,g_repID
);
302 SchemaPlay((Label
*)"repfail",NULL
);
305 ShockStringFetch(temp
,sizeof(temp
),"RepFail","misc");
306 ShockOverlayAddText(temp
,DEFAULT_MSG_TIME
);
312 //--------------------------------------------------------------------------------------
313 bool ShockRepHandleMouse(Point pt
)
316 r
= ShockOverlayGetRect(kOverlayRep
);
317 // get the mouse location and make it rect-relative
320 state
= ObjGetObjState(g_repID
);
322 if (state
== kObjStateBroken
)
326 slot
= RepFindSlot(pt
);
329 gRepSelection
= slot
+ gRepFocus
;
330 ShockReplicate(gRepSelection
);
335 //--------------------------------------------------------------------------------------
336 #define TEXT_OFFSET 37 // 68
337 void ShockRepDraw(void)
342 IObjectSystem
*objsys
;
345 int dx
,dy
,w
,h
,textwidth
;
348 AutoAppIPtr(GameStrings
);
350 r
= ShockOverlayGetRect(kOverlayRep
);
352 objsys
= AppGetObj(IObjectSystem
);
354 if (g_repID
== OBJ_NULL
)
357 // draw the replicator background
358 state
= ObjGetObjState(g_repID
);
360 if (state
== kObjStateBroken
)
362 DrawByHandle(gHndBroken
, r
.ul
);
366 DrawByHandle(gHndRep
, r
.ul
);
368 gr_set_fcolor(gShockTextColor
);
370 // draw in obj icons for the available loot
371 for (i
=gRepFocus
; i
< gRepFocus
+ 4; i
++)
373 RepContentsGetObj(g_repID
, i
, temp
);
374 if (strlen(temp
) > 0)
376 // get the archetype of the given object
377 arch
= objsys
->GetObjectNamed(temp
);
379 drawrect
= obj_rects
[i
- gRepFocus
];
380 RectMove(&drawrect
, r
.ul
);
381 ShockInvObjDraw(arch
, drawrect
.ul
.x
, drawrect
.ul
.y
); // r.ul.x + obj_rects[i].ul.x, r.ul.y + obj_rects[i].ul.y);
383 sprintf(temp
,"%03d",RepContentsGetCost(g_repID
,i
));
384 dx
= drawrect
.ul
.x
+ 9;
385 dy
= drawrect
.lr
.y
- 11;
386 gr_font_string(gShockFont
,temp
,dx
,dy
);
388 //str = pGameStrings->FetchObjString(arch,PROP_OBJNAME_NAME);
389 //strcpy(temp,str); // need a copy since we are wrapping
390 ObjGetObjShortNameSubst(arch
,temp
,sizeof(temp
));
391 textwidth
= RectWidth(&obj_rects
[i
- gRepFocus
]) - TEXT_OFFSET
;
392 gr_font_string_wrap(gShockFont
,temp
,textwidth
);
393 h
= gr_font_string_height(gShockFont
,temp
);
394 w
= gr_font_string_width(gShockFont
, temp
);
395 dx
= drawrect
.ul
.x
+ TEXT_OFFSET
;
396 dy
= drawrect
.ul
.y
+ 4;
397 gr_font_string(gShockFont
,temp
,dx
,dy
);
399 if (i
== gRepSelection
)
400 DrawByHandle(gHndSelect
, drawrect
.ul
);
403 // draw in the player's total nanite quantity
404 sprintf(temp
,"%04d",ShockInvNaniteTotal());
405 gr_font_string(gShockFont
,temp
,r
.ul
.x
+ 104, r
.ul
.y
+ 274);
407 // draw in the close button
408 LGadDrawBox(VB(&close_button
),NULL
);
409 // and the buy button
410 //LGadDrawBox(VB(&buy_button),NULL);
412 // draw the up and down buttons (only if appropriate)
414 //LGadDrawBox(VB(&up_button),NULL);
415 //if (gRepFocus < gRepFocusMax)
416 //LGadDrawBox(VB(&down_button),NULL);
418 //--------------------------------------------------------------------------------------
419 // Property Definitions
420 //--------------------------------------------------------------------------------------
422 /////////////////////////////////////////////////////////////
423 // Replicator contents (replicator-side)
424 /////////////////////////////////////////////////////////////
426 // the all new improved property system...
428 class cRepContentsDataOps
: public cClassDataOps
<sRepContents
>
433 class cRepContentsStore
: public cHashPropertyStore
<cRepContentsDataOps
>
437 // property implementation class
438 class cRepContentsProperty
: public cSpecificProperty
<IRepContentsProperty
, &IID_IRepContentsProperty
, sRepContents
*, cRepContentsStore
>
440 typedef cSpecificProperty
<IRepContentsProperty
, &IID_IRepContentsProperty
, sRepContents
*, cRepContentsStore
> cParent
;
443 cRepContentsProperty(const sPropertyDesc
* desc
)
448 STANDARD_DESCRIBE_TYPE(sRepContents
);
452 IRepContentsProperty
*g_RepContentsProperty
;
453 IRepContentsProperty
*g_RepContentsHackedProperty
;
455 static sFieldDesc RepContentsFields
[] =
457 {"Obj 1 Name", kFieldTypeString
, FieldLocation(sRepContents
, m_objs
[0]),},
458 {"Obj 1 Cost", kFieldTypeInt
, FieldLocation(sRepContents
, m_costs
[0]),},
459 {"Obj 2 Name", kFieldTypeString
, FieldLocation(sRepContents
, m_objs
[1]),},
460 {"Obj 2 Cost", kFieldTypeInt
, FieldLocation(sRepContents
, m_costs
[1]),},
461 {"Obj 3 Name", kFieldTypeString
, FieldLocation(sRepContents
, m_objs
[2]),},
462 {"Obj 3 Cost", kFieldTypeInt
, FieldLocation(sRepContents
, m_costs
[2]),},
463 {"Obj 4 Name", kFieldTypeString
, FieldLocation(sRepContents
, m_objs
[3]),},
464 {"Obj 4 Cost", kFieldTypeInt
, FieldLocation(sRepContents
, m_costs
[3]),},
465 {"Obj 5 Name", kFieldTypeString
, FieldLocation(sRepContents
, m_objs
[4]),},
466 {"Obj 5 Cost", kFieldTypeInt
, FieldLocation(sRepContents
, m_costs
[4]),},
467 {"Obj 6 Name", kFieldTypeString
, FieldLocation(sRepContents
, m_objs
[5]),},
468 {"Obj 6 Cost", kFieldTypeInt
, FieldLocation(sRepContents
, m_costs
[5]),},
471 static sStructDesc RepContentsStructDesc
=
472 StructDescBuild(sRepContents
, kStructFlagNone
, RepContentsFields
);
474 //--------------------------------------------------------------------------------------
475 IRepContentsProperty
*CreateRepContentsProperty(sPropertyDesc
*desc
, ePropertyImpl impl
)
477 StructDescRegister(&RepContentsStructDesc
);
478 return new cRepContentsProperty(desc
);
481 static sPropertyDesc RepContentsDesc
=
485 {"GameSys", "Rep. Contents"},
488 static sPropertyDesc RepContentsHackedDesc
=
490 PROP_REPCONTENTSHACK
, 0,
492 {"GameSys", "Rep. Hack Contents"},
495 //--------------------------------------------------------------------------------------
496 void RepContentsPropertyInit()
498 g_RepContentsProperty
= CreateRepContentsProperty(&RepContentsDesc
, kPropertyImplSparse
);
499 g_RepContentsHackedProperty
= CreateRepContentsProperty(&RepContentsHackedDesc
, kPropertyImplSparse
);
502 //--------------------------------------------------------------------------------------
503 BOOL
RepContentsGet(ObjID objID
, sRepContents
**ppRepContents
)
507 st
= ObjGetObjState(objID
);
508 if (st
== kObjStateHacked
)
509 return g_RepContentsHackedProperty
->Get(objID
, ppRepContents
);
511 return g_RepContentsProperty
->Get(objID
, ppRepContents
);
514 //--------------------------------------------------------------------------------------
515 bool RepContentsGetObj(ObjID objID
, int slot
, char *name
)
517 sRepContents
*pRepContents
;
520 st
= ObjGetObjState(objID
);
521 if (st
== kObjStateHacked
)
523 if (g_RepContentsHackedProperty
->Get(objID
, &pRepContents
))
525 strcpy(name
,pRepContents
->m_objs
[slot
]);
531 if (g_RepContentsProperty
->Get(objID
, &pRepContents
))
533 strcpy(name
,pRepContents
->m_objs
[slot
]);
540 //--------------------------------------------------------------------------------------
541 int RepContentsGetCost(ObjID objID
, int slot
)
543 sRepContents
*pRepContents
;
546 st
= ObjGetObjState(objID
);
548 if (st
== kObjStateHacked
)
550 if (g_RepContentsHackedProperty
->Get(objID
, &pRepContents
))
552 retval
=pRepContents
->m_costs
[slot
];
557 if (g_RepContentsProperty
->Get(objID
, &pRepContents
))
559 retval
=pRepContents
->m_costs
[slot
];
562 AutoAppIPtr(ShockPlayer
);
563 if (pShockPlayer
->HasTrait(PlayerObject(),kTraitReplicator
))
564 retval
= retval
* 8 / 10;
566 // now multiply the cost by difficulty param
567 AutoAppIPtr(QuestData
);
568 sDiffParams
* params
= GetDiffParams();
569 int diff
= pQuestData
->Get(DIFF_QVAR
);
570 retval
= float(retval
) * params
->m_repcost
[diff
];
575 //--------------------------------------------------------------------------------------
577 static bool up_cb(short action, void* data, LGadBox* vb)
579 if (action != BUTTONGADG_LCLICK)
582 SchemaPlay((Label *)"bscroll",NULL);
584 gRepFocus = gRepFocus - 1;
589 //--------------------------------------------------------------------------------------
590 static bool down_cb(short action, void* data, LGadBox* vb)
592 if (action != BUTTONGADG_LCLICK)
595 SchemaPlay((Label *)"bscroll",NULL);
597 // don't scroll down into illegal turf
598 if (gRepFocus + 1 > gRepFocusMax)
601 gRepFocus = gRepFocus + 1;
605 //--------------------------------------------------------------------------------------
607 static bool buy_cb(short action, void* data, LGadBox* vb)
609 if (action != BUTTONGADG_LCLICK)
611 if (ShockReplicate(gRepSelection))
612 uiDefer(DeferOverlayClose,(void *)kOverlayRep);
616 //--------------------------------------------------------------------------------------
617 static bool close_cb(short action
, void* data
, LGadBox
* vb
)
619 if (action
!= BUTTONGADG_LCLICK
)
621 uiDefer(DeferOverlayClose
,(void *)kOverlayRep
);
624 //--------------------------------------------------------------------------------------
625 static void SetupElem(DrawElement
*dep
, grs_bitmap
**bmps
)
627 dep
->draw_type
= DRAWTYPE_BITMAPOFFSET
;
628 dep
->draw_data
= bmps
;
629 dep
->draw_data2
= (void *)4; // should be 2 but hackery required
631 //--------------------------------------------------------------------------------------
632 static void BuildInterfaceButtons(void)
634 Rect r
= ShockOverlayGetRect(kOverlayRep
);
636 // set up the continue button
637 SetupElem(&close_elem
, close_bitmaps
);
638 LGadCreateButtonArgs(&close_button
, LGadCurrentRoot(), close_rect
.ul
.x
+ r
.ul
.x
, close_rect
.ul
.y
+ r
.ul
.y
,
639 RectWidth(&close_rect
), RectHeight(&close_rect
), &close_elem
, close_cb
, 0);
642 SetupElem(&buy_elem, buy_bitmaps);
643 LGadCreateButtonArgs(&buy_button, LGadCurrentRoot(), buy_rect.ul.x + r.ul.x, buy_rect.ul.y + r.ul.y,
644 RectWidth(&buy_rect), RectHeight(&buy_rect), &buy_elem, buy_cb, 0);
648 SetupElem(&up_elem, up_bitmaps);
649 LGadCreateButtonArgs(&up_button, LGadCurrentRoot(), up_rect.ul.x + r.ul.x, up_rect.ul.y + r.ul.y,
650 RectWidth(&up_rect), RectHeight(&up_rect), &up_elem, up_cb, 0);
652 SetupElem(&down_elem, down_bitmaps);
653 LGadCreateButtonArgs(&down_button, LGadCurrentRoot(), down_rect.ul.x + r.ul.x, down_rect.ul.y + r.ul.y,
654 RectWidth(&down_rect), RectHeight(&down_rect), &down_elem, down_cb, 0);
658 //--------------------------------------------------------------------------------------
659 static void DestroyInterfaceButtons(void)
661 LGadDestroyBox(VB(&close_button
),FALSE
);
662 //LGadDestroyBox(VB(&buy_button),FALSE);
663 //LGadDestroyBox(VB(&down_button),FALSE);
664 //LGadDestroyBox(VB(&up_button),FALSE);
666 //--------------------------------------------------------------------------------------
667 void ShockRepStateChange(int which
)
670 extern bool gNoMouseToggle;
671 gNoMouseToggle = ShockOverlayCheck(which);
673 if (ShockOverlayCheck(which
))
675 //repMusicSchema = SchemaPlay((const Label*)"RepMusic", NULL);
676 BuildInterfaceButtons();
680 o
= ShockOverlayGetObj();
681 state
= ObjGetObjState(g_repID
);
683 if (state
== kObjStateBroken
)
685 ShockHRMPlugSetMode(1, g_repID
);
686 ShockOverlayChange(kOverlayHRMPlug
, kOverlayModeOn
);
688 else if (gPropHackDiff
->IsRelevant(g_repID
) && !(state
== kObjStateHacked
))
690 ShockHRMPlugSetMode(0, g_repID
);
691 ShockOverlayChange(kOverlayHRMPlug
, kOverlayModeOn
);
696 //SchemaPlayHalt(repMusicSchema);
697 DestroyInterfaceButtons();
698 ShockOverlayChange(kOverlayHRMPlug
, kOverlayModeOff
);
701 //--------------------------------------------------------------------------------------
702 void ShockRepSetup(ObjID rep
)
707 ShockOverlayChange(kOverlayRep
,kOverlayModeOn
);
708 ShockOverlaySetObj(kOverlayRep
, rep
);
709 for (i
= 0; i
< NUM_REPLICATOR_CONTENTS
- NUM_REPLICATOR_BOXES
; i
++)
711 cost
= RepContentsGetCost(rep
,i
+ NUM_REPLICATOR_BOXES
);
718 state
= ObjGetObjState(rep
);
720 if (state
!= kObjStateBroken
)
722 SchemaPlay((Label
*)"replicator1e",NULL
);
725 //--------------------------------------------------------------------------------------
726 sOverlayFunc OverlayRep
= {
727 ShockRepDraw
, // draw
728 ShockRepInit
, // init
729 ShockRepTerm
, // term
730 ShockRepHandleMouse
, // mouse
731 NULL
, // dclick (really use)
735 "subpanel_op", // upschema
736 "subpanel_cl", // downschema
737 ShockRepStateChange
, // state
738 NULL
, // transparency