2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // $Header: r:/t2repos/thief2/src/shock/shkhrm.cpp,v 1.55 2000/02/19 13:25:26 toml Exp $
49 // ui library not C++ ized properly yet
56 #include <dbmem.h> // must be last header!
59 #define NUM_HRM_MODES 3
61 static IRes
*gBackHnd
[3];
62 static IRes
*gNodeHnd
[4];
63 static IRes
*gModeHnd
[4][3];
64 static IRes
*gBarHnd
[2];
66 static Rect full_rect
= {{LMFD_X
, LMFD_Y
}, {LMFD_X
+ LMFD_W
, LMFD_Y
+ LMFD_H
}};
67 static Rect close_rect
= {{163,8},{163 + 20, 8 + 21}};
69 static LGadButton close_button
;
70 static DrawElement close_elem
;
71 static IRes
*close_handles
[2];
72 static grs_bitmap
*close_bitmaps
[4];
77 static Rect doit_rect
= {{157,232},{157 + 19, 232 + 55}};
78 static LGadButton doit_button
;
79 static DrawElement doit_elem
;
80 static IRes
*doit_handles
[2];
81 static grs_bitmap
*doit_bitmaps
[4];
83 static IRes
*reset_handle
;
85 static int gHRMMode
= 0;
87 static uint gHRMFlags
= 0;
89 #define MAX_JARGON_LINES 12
90 static char gJargonLines
[MAX_JARGON_LINES
][255];
91 static char gJargonText
[1024];
92 static int gJargonNum
;
93 static int gJargonTeletype
;
94 static tSimTime gJargonTime
;
108 eHRMGameMode gHRMGameMode
;
119 static char *nodenames
[] = { "", "hrmon","hrmburn","hrmmine" };
120 static char *postfixes
[] = { "H","R","M" };
121 static char *modenames
[] = { "lose","win","pay","fail" };
122 static char *backnames
[] = { "hack", "repair", "modify", };
123 static char *barnames
[] = { "hrmbarh", "hrmbarv", };
125 static eHRMState gHRMState
[MATRIX_X
][MATRIX_Y
];
127 static int gHRMBoards
[NUM_HRM_MODES
][MATRIX_Y
][MATRIX_X
] =
154 // okay, I admit this is getting hideous
155 BOOL gHRMPsi
= FALSE
;
158 static ITechInfoProperty
*hrm_props
[NUM_HRM_MODES
];
163 kHRMFlagUseINT
= 0x1,
168 kHRMResultNone
= 0x0,
170 kHRMResultLoss
= 0x2,
174 #define TEXT_Y 12 // goal
175 #define TEXT_Y2 180 // jargon
178 #define TELETYPE_SPEED 10
180 //--------------------------------------------------------------------------------------
184 for (i
=0; i
< MAX_JARGON_LINES
; i
++)
186 strcpy(gJargonLines
[i
],"");
188 strcpy(gJargonText
,"");
192 //--------------------------------------------------------------------------------------
193 void JargonAdd(char *text
)
198 h
= gr_font_string_height(gShockFont
, gJargonText
);
199 while ((gJargonNum
== MAX_JARGON_LINES
) || (h
> JARGON_H
))
201 //ConfigSpew("hrm_spew",("removing old line\n"));
203 // copy everything down by one
204 for (i
=0; i
< MAX_JARGON_LINES
- 1; i
++)
205 strcpy(gJargonLines
[i
],gJargonLines
[i
+1]);
207 // reset pointer back one
210 strcpy(gJargonText
,"");
211 for (i
=0; i
< gJargonNum
; i
++)
213 strcat(gJargonText
,gJargonLines
[i
]);
215 gr_font_string_wrap(gShockFont
, gJargonText
, TEXT_W
);
216 h
= gr_font_string_height(gShockFont
, gJargonText
);
219 tSimTime simtime
= GetSimTime();
220 if (gJargonTime
== 0)
222 gJargonTime
= simtime
- (strlen(gJargonText
) * TELETYPE_SPEED
);
223 //ConfigSpew("hrm_spew",("resetting jargontime to %d\n",gJargonTime));
226 strcpy(gJargonLines
[gJargonNum
],text
);
228 ConfigSpew("hrm_spew",("adding text: %s",text
));
230 // reassemble main text
231 gr_font_string_unwrap(gJargonText
);
232 strcat(gJargonText
,gJargonLines
[gJargonNum
-1]);
233 gr_font_string_wrap(gShockFont
, gJargonText
, TEXT_W
);
235 //--------------------------------------------------------------------------------------
236 static void ResetBoard(void)
239 for (x
= 0; x
< MATRIX_X
; x
++)
241 for (y
= 0; y
< MATRIX_Y
; y
++)
243 gHRMState
[x
][y
] = (eHRMState
)gHRMBoards
[gHRMMode
][y
][x
]; // yes, this is reversed!
247 //--------------------------------------------------------------------------------------
248 // actually resolve the effect!
250 static void ShockHRMTriggerEffect(eHRMResult result
)
252 uint flags
= kHRMFlagNone
;
254 ObjID o
= ShockOverlayGetObj();
255 ObjID plr
= PlayerObject();
257 AutoAppIPtr(ShockPlayer
);
258 AutoAppIPtr(ScriptMan
);
262 sprintf(name
,"%sResult",backnames
[gHRMMode
]);
263 ShockStringFetch(temp
,sizeof(temp
),name
,"hrm",result
);
264 if (strlen(temp
) > 0)
265 ShockOverlayAddText(temp
,DEFAULT_MSG_TIME
);
267 // no effect, then just reset the board
268 // maybe this should just lock out input and
269 // force the player to reset the board?
270 if (result
== kHRMResultNone
)
273 gHRMGameMode
= kHRMModeUnwinnable
;
275 //SchemaPlay((Label *)"login",NULL);
282 if (result
== kHRMResultWin
)
284 // send a "done hacking" message to the object
285 sScrMsg
msg(o
,"HackSuccess");
286 // We want to run this script locally, even if we're a client:
287 msg
.flags
|= kSMF_MsgSendToProxy
;
288 pScriptMan
->SendMessage(&msg
);
289 SchemaPlay((Label
*)"hack_success",NULL
);
293 ObjSetObjState(o
,kObjStateBroken
);
294 SchemaPlay((Label
*)"hack_critical",NULL
);
297 sScrMsg
msg(o
,"HackCritfail");
298 msg
.flags
|= kSMF_MsgPostToOwner
;
299 pScriptMan
->SendMessage(&msg
);
304 if (result
== kHRMResultWin
)
306 ObjSetObjState(o
,kObjStateNormal
);
308 // improve it's condition as well, if it is a weapon
309 if (ObjHasGunState(o
))
311 float cond
= GunGetCondition(o
);
313 if (cond
> 100) cond
= 100;
314 GunSetCondition(o
,cond
);
317 SchemaPlay((Label
*)"hack_success",NULL
);
323 // okay, is this an equipped item? If so, we need to unequip it
324 AutoAppIPtr(ContainSys
);
325 eContainType ctype
= pContainSys
->IsHeld(PlayerObject(),o
);
326 if (ctype
!= ECONTAIN_NULL
)
328 pShockPlayer
->Equip(PlayerObject(),(ePlayerEquip
)(ctype
- SHOCKCONTAIN_PDOLLBASE
), OBJ_NULL
, FALSE
);
331 //ObjSetObjState(o,kObjStateDestroyed);
332 AutoAppIPtr(ObjectSystem
);
333 pObjectSystem
->Destroy(o
);
336 SchemaPlay((Label
*)"hack_critical",NULL
);
340 if (result
== kHRMResultWin
)
342 int modlevel
= GunGetModification(o
);
345 GunSetModification(o
, modlevel
+ 1);
346 SchemaPlay((Label
*)"hack_success",NULL
);
352 ObjSetObjState(o
,kObjStateBroken
);
354 SchemaPlay((Label
*)"hack_critical",NULL
);
361 if (result
== kHRMResultWin
)
362 gHRMGameMode
= kHRMModeWin
;
364 gHRMGameMode
= kHRMModeLose
;
366 //--------------------------------------------------------------------------------------
367 static eTechSkills
FindSkill()
369 eTechSkills useskill
;
372 case 0: useskill
= kTechHacking
; break;
373 case 1: useskill
= kTechRepair
; break;
374 case 2: useskill
= kTechModify
; break;
376 Warning(("FindSkill: invalid HRM mode %d!\n",gHRMMode
));
377 useskill
= kTechHacking
;
382 //--------------------------------------------------------------------------------------
384 static int FindCost()
389 ObjID o
= ShockOverlayGetObj();
391 if (!hrm_props
[gHRMMode
]->Get(o
,&ti
))
396 retval
= BASE_COST
* factor
;
398 AutoAppIPtr(ShockPlayer
);
399 if ((gHRMMode
== 2) && pShockPlayer
->HasTrait(PlayerObject(),kTraitTinker
))
403 // psi only costs half as much
404 // this removed 6/17/99 as retuning -- Xemu
414 //--------------------------------------------------------------------------------------
415 static bool PayNanites()
418 ObjID plr
= PlayerObject();
419 AutoAppIPtr(ShockPlayer
);
428 if (ShockInvNaniteTotal() < cost
)
430 SchemaPlay((Label
*)"login",NULL
);
433 ShockStringFetch(temp
,sizeof(temp
),"NoNoNanites","misc");
434 ShockOverlayAddText(temp
,DEFAULT_MSG_TIME
);
438 ShockInvPayNanites(cost
);
442 AutoAppIPtr(PlayerPsi
);
443 int psipoints
= pPlayerPsi
->GetPoints();
445 if (psipoints
< cost
)
448 ShockStringFetch(temp
,sizeof(temp
),"NoNoPsi","misc");
449 ShockOverlayAddText(temp
,DEFAULT_MSG_TIME
);
453 pPlayerPsi
->SetPoints(psipoints
- cost
);
459 //--------------------------------------------------------------------------------------
463 AutoAppIPtr(ShockPlayer
);
467 case kTechHacking
: soft
= pShockPlayer
->GetEquip(PlayerObject(), kEquipHack
); break;
468 case kTechRepair
: soft
= pShockPlayer
->GetEquip(PlayerObject(), kEquipRepair
); break;
469 case kTechModify
: soft
= pShockPlayer
->GetEquip(PlayerObject(), kEquipModify
); break;
473 if (soft
!= OBJ_NULL
)
474 gPropSoftwareLevel
->Get(soft
, &softlevel
);
478 //--------------------------------------------------------------------------------------
479 static int HRMSkill()
481 int skillval
, softlevel
;
483 AutoAppIPtr(ShockPlayer
);
486 skillval
= pShockPlayer
->GetStat(kStatPsi
);
487 if (PsiOverloaded(PlayerObject(),kPsiCyberHack
))
488 skillval
= skillval
+ 2;
489 skillval
= (skillval
+ 1) / 2; // the +1 for rounding up
492 skillval
= pShockPlayer
->GetTechSkill(FindSkill());
493 // if (skillval >= MAX_SKILL_VAL)
494 // skillval = MAX_SKILL_VAL - 1;
495 if (pShockPlayer
->HasImplant(PlayerObject(), kImplantTech
) && !gHRMPsi
)
500 softlevel
= FindSoftLevel();
501 skillval
= skillval
+ (softlevel
);
503 skillval
= skillval
+ gHRMBonus
;
507 //--------------------------------------------------------------------------------------
510 AutoAppIPtr(ShockPlayer
);
514 statval
= pShockPlayer
->GetStat(kStatPsi
);
515 if (PsiOverloaded(PlayerObject(),kPsiCyberHack
))
516 statval
= statval
+ 2;
517 statval
= (statval
+ 1) / 2;
520 statval
= pShockPlayer
->GetStat(kStatCyber
);
525 if (!hrm_props[gHRMMode]->Get(o,&ti))
528 *succeed = ti->m_success;
529 *critfail = ti->m_critfail;
531 AutoAppIPtr(ShockPlayer);
534 skillval = HRMSkill();
537 //--------------------------------------------------------------------------------------
538 int FindChance(sTechInfo
*ti
)
542 params
= GetHRMParams();
544 chance
= ti
->m_success
+
545 (HRMSkill() * params
->m_skillSuccessBonus
) +
546 (HRMStat() * params
->m_statSuccessBonus
);
551 //--------------------------------------------------------------------------------------
552 int FindMines(sTechInfo
*ti
)
556 params
= GetHRMParams();
558 num_mines
= ti
->m_critfail
559 - (HRMSkill() * params
->m_skillCritfailBonus
)
560 - (HRMStat() * params
->m_statCritfailBonus
);
563 static int BoardValue(int x
, int y
)
565 if ((x
< 0) || (y
< 0) || (x
>= MATRIX_X
) || (y
>= MATRIX_Y
))
568 if (gHRMState
[x
][y
] == kHRMStateLit
)
573 //--------------------------------------------------------------------------------------
574 // board has changed at location X, see whether this causes a win
575 // or an un-winnable situation
576 static void EvaluateBoard(Point loc
)
585 // this is kind of retarded, I admit
586 if (BoardValue(x
-2,y
) + BoardValue(x
-1,y
) + BoardValue(x
,y
) == 3)
588 if (BoardValue(x
-1,y
) + BoardValue(x
,y
) + BoardValue(x
+1,y
) == 3)
590 if (BoardValue(x
,y
) + BoardValue(x
+1,y
) + BoardValue(x
+2,y
) == 3)
592 if (BoardValue(x
,y
-2) + BoardValue(x
,y
-1) + BoardValue(x
,y
) == 3)
594 if (BoardValue(x
,y
-1) + BoardValue(x
,y
) + BoardValue(x
,y
+1) == 3)
596 if (BoardValue(x
,y
) + BoardValue(x
,y
+1) + BoardValue(x
,y
+2) == 3)
602 ShockHRMTriggerEffect(kHRMResultWin
);
605 ShockStringFetch(temp
,sizeof(temp
),"JargonWin","jargon",gHRMMode
);
610 // now count open squares
612 for (x
=0; x
< MATRIX_X
; x
++)
614 for (y
= 0; y
< MATRIX_Y
; y
++)
616 if ((gHRMState
[x
][y
] == kHRMStateFree
) || (gHRMState
[x
][y
] == kHRMStateMine
))
621 // if none left, game is unwinnable
624 ShockHRMTriggerEffect(kHRMResultNone
);
627 //--------------------------------------------------------------------------------------
628 static void PlaceMines()
630 int i
, num_mines
, num_free
, r
;
634 ObjID o
= ShockOverlayGetObj();
636 if (!hrm_props
[gHRMMode
]->Get(o
,&ti
))
639 // figure out how many mines to place
640 num_mines
= FindMines(ti
);
642 // how many blank spaces do we have?
644 for (x
=0; x
< MATRIX_X
; x
++)
646 for (y
= 0; y
< MATRIX_Y
; y
++)
648 if (gHRMState
[x
][y
] == kHRMStateFree
)
652 ConfigSpew("hrm_spew",("%d free spaces on board, %d mines\n",num_free
,num_mines
));
654 for (i
=0; (i
< num_mines
) && (num_free
> 0); i
++)
656 // choose a random location
658 // if we have tried too many times, bail out
659 r
= (Rand() % num_free
) + 1;
662 // count up until we find the Nth free spot
663 // turn it into a mine square
666 for (x
=0; !placed
&& (x
< MATRIX_X
); x
++)
668 for (y
=0; !placed
&& (y
< MATRIX_Y
); y
++)
670 if (gHRMState
[x
][y
] == kHRMStateFree
)
674 ConfigSpew("hrm_spew",("Placing mine at %d, %d\n",x
,y
));
675 gHRMState
[x
][y
] = kHRMStateMine
;
682 //--------------------------------------------------------------------------------------
683 static void PlayPiece(Point loc
)
687 float diceval
,chance
;
693 o
= ShockOverlayGetObj();
695 state
= gHRMState
[loc
.x
][loc
.y
];
696 if ((state
== kHRMStateLit
) || (state
== kHRMStateDead
) || (state
== kHRMStateEmpty
))
698 // not a valid play, give feedback
699 SchemaPlay((Label
*)"login",NULL
);
703 // are we playing on a "mine" square?
704 mined
= (state
== kHRMStateMine
);
706 diceval
= (Rand() % 10000) / 100.0F
;
708 if (!hrm_props
[gHRMMode
]->Get(o
,&ti
))
711 chance
= FindChance(ti
);
713 ConfigSpew("hrm_spew",("diceval %g vs success %g\n",diceval
,chance
));
715 if (diceval
<= chance
)
717 gHRMState
[loc
.x
][loc
.y
] = kHRMStateLit
;
721 ShockStringFetch(temp
,sizeof(temp
),"JargonLit","jargon",((r
+1) * 10) + gHRMMode
);
724 ShockStringFetch(temp
,sizeof(temp
),"JargonMineLit","jargon", gHRMMode
);
732 ShockStringFetch(temp
,sizeof(temp
),"JargonMineBurnt","jargon", gHRMMode
);
734 ShockHRMTriggerEffect(kHRMResultLoss
);
739 ShockStringFetch(temp
,sizeof(temp
),"JargonBurnt","jargon",((r
+1) * 10) + gHRMMode
);
742 gHRMState
[loc
.x
][loc
.y
] = kHRMStateDead
;
748 //--------------------------------------------------------------------------------------
756 static Rect board_rect
= {{BOARD_X
,BOARD_Y
},{BOARD_X
+ (BOARD_DX
* MATRIX_X
),BOARD_Y
+ (BOARD_DY
* MATRIX_Y
)}};
758 static void DrawBoard()
763 Rect r
= ShockOverlayGetRect(kOverlayHRM
);
765 for (x
=0 ; x
< MATRIX_X
; x
++)
767 for (y
=0; y
< MATRIX_Y
; y
++)
769 state
= gHRMState
[x
][y
];
770 if ((state
!= kHRMStateEmpty
) && (state
!= kHRMStateFree
))
772 draw
.x
= BOARD_X
+ (x
* BOARD_DX
) + r
.ul
.x
;
773 draw
.y
= BOARD_Y
+ (y
* BOARD_DY
) + r
.ul
.y
;
774 DrawByHandle(gNodeHnd
[state
],draw
);
776 if (state
== kHRMStateLit
)
778 // are we right-connected?
779 if (x
< MATRIX_X
- 1)
781 if (gHRMState
[x
+1][y
] == kHRMStateLit
)
782 DrawByHandle(gBarHnd
[0],draw
);
784 if (y
< MATRIX_Y
- 1)
786 if (gHRMState
[x
][y
+1] == kHRMStateLit
)
787 DrawByHandle(gBarHnd
[1],draw
);
793 //--------------------------------------------------------------------------------------
794 static ePlayerEquip g_softslots
[] = { kEquipHack
, kEquipRepair
, kEquipModify
};
795 static ePlayerEquip
FindSoftSlot()
798 if ((gHRMMode
< 0) || (gHRMMode
> 2))
800 Warning(("FindSoftSlot: asked for invalid slot %d!\n",gHRMMode
));
805 return(g_softslots
[usemode
]);
807 //--------------------------------------------------------------------------------------
808 void ShockHRMInit(int )
813 for (i
=1; i
< 4; i
++)
815 sprintf(temp
,"%s",nodenames
[i
]);
816 gNodeHnd
[i
] = LoadPCX(temp
);
819 for (i
=0; i
< 2; i
++)
821 gBarHnd
[i
] = LoadPCX(barnames
[i
]);
824 for (i
=0; i
< 4; i
++)
826 for (j
=0; j
< 3; j
++)
828 sprintf(temp
,"%s%s",modenames
[i
],postfixes
[j
]);
829 gModeHnd
[i
][j
] = LoadPCX(temp
);
833 close_handles
[0] = LoadPCX("closeoff"); // LoadPCX(temp);
834 close_handles
[1] = LoadPCX("Closeon"); // LoadPCX(temp);
835 close_bitmaps
[0] = (grs_bitmap
*) close_handles
[0]->Lock();
836 close_bitmaps
[1] = (grs_bitmap
*) close_handles
[1]->Lock();
837 for (i
= 2; i
< 4; i
++)
839 close_bitmaps
[i
] = close_bitmaps
[0];
842 sprintf(temp
,"start0");
843 doit_handles
[0] = LoadPCX(temp
);
844 sprintf(temp
,"start1");
845 doit_handles
[1] = LoadPCX(temp
);
846 doit_bitmaps
[0] = (grs_bitmap
*) doit_handles
[0]->Lock();
847 doit_bitmaps
[1] = (grs_bitmap
*) doit_handles
[1]->Lock();
848 for (i
= 2; i
< 4; i
++)
850 doit_bitmaps
[i
] = doit_bitmaps
[0];
853 for (i
=0; i
< 3; i
++)
854 gBackHnd
[i
] = LoadPCX(backnames
[i
]);
856 hrm_props
[0] = gPropHackDiff
;
857 hrm_props
[1] = gPropRepairDiff
;
858 hrm_props
[2] = gPropModifyDiff
;
860 reset_handle
= LoadPCX("reset0");
862 SetLeftMFDRect(kOverlayHRM
, full_rect
);
865 //--------------------------------------------------------------------------------------
866 void ShockHRMTerm(void)
870 for (i
=0; i
< 3; i
++)
871 SafeFreeHnd(&gBackHnd
[i
]);
873 for (i
=0; i
< 2; i
++)
874 SafeFreeHnd(&gBarHnd
[i
]);
876 for (i
=0; i
< 4; i
++)
878 SafeFreeHnd(&gNodeHnd
[i
]);
881 for (i
=0; i
< 4; i
++)
882 for (j
=0; j
< 3; j
++)
883 SafeFreeHnd(&gModeHnd
[i
][j
]);
885 close_handles
[0]->Unlock();
886 close_handles
[1]->Unlock();
887 SafeFreeHnd(&close_handles
[0]);
888 SafeFreeHnd(&close_handles
[1]);
889 doit_handles
[0]->Unlock();
890 doit_handles
[1]->Unlock();
891 SafeFreeHnd(&doit_handles
[0]);
892 SafeFreeHnd(&doit_handles
[1]);
894 SafeFreeHnd(&reset_handle
);
897 //--------------------------------------------------------------------------------------
898 static Rect help_rects
[] = {
903 {{-1,-1},{-1,-1}}, //{{159,149},{159 + 19, 149 + 140}},
904 {{13,271},{154,288}},
905 {{13,248},{154,266}},
908 #define NUM_HELP_RECTS (sizeof(help_rects)/sizeof(Rect))
910 static void DrawHelpText(Point mpt
)
918 Rect r
= ShockOverlayGetRect(kOverlayHRM
);
920 o
= ShockOverlayGetObj();
921 plr
= PlayerObject();
922 AutoAppIPtr(GameStrings
);
923 AutoAppIPtr(ShockPlayer
);
928 for (i=0; i < NUM_HELP_RECTS; i++)
930 if (RectTestPt(&help_rects[i], mpt))
934 ShockStringFetch(temp,sizeof(temp),"HRMHelp","hrm",i);
940 // also display the effect of the tech op
944 str
= pGameStrings
->FetchObjString(o
, PROP_HACKTEXT_NAME
);
948 ShockStringFetch(temp
,sizeof(temp
),"RepairText","hrm");
951 modlevel
= GunGetModification(o
);
952 // adjust if we've just won
953 if (gHRMGameMode
== kHRMModeWin
)
959 str
= pGameStrings
->FetchObjString(o
, PROP_MODIFY1TEXT_NAME
);
963 str
= pGameStrings
->FetchObjString(o
, PROP_MODIFY2TEXT_NAME
);
967 ShockStringFetch(temp
,sizeof(temp
),"ModifyResult3","misc");
972 gr_font_string_wrap(gShockFont
, temp
, TEXT_W
);
973 gr_set_fcolor(gShockTextColor
);
974 gr_font_string(gShockFont
, temp
, TEXT_X
+ r
.ul
.x
, TEXT_Y
+ r
.ul
.y
);
977 tSimTime simtime
= GetSimTime();
979 if (gJargonTime
== 0)
981 gJargonTeletype
= strlen(gJargonText
);
985 gJargonTeletype
= (simtime
- gJargonTime
) / TELETYPE_SPEED
;
986 if (gJargonTeletype
> strlen(gJargonText
))
990 //ConfigSpew("hrm_spew",("JargonTeletype = %d, strlen = %d\n",gJargonTeletype,strlen(gJargonText)));
991 strcpy(temp
,gJargonText
);
992 temp
[gJargonTeletype
] = '\0';
993 gr_font_string(gShockFont
, temp
, TEXT_X
+ r
.ul
.x
, TEXT_Y2
+ r
.ul
.y
);
997 if (hrm_props
[gHRMMode
]->Get(o
,&ti
))
999 chance
= FindChance(ti
);
1000 sprintf(temp
,"%d%%",100 - chance
);
1001 gr_font_string(gShockFont
, temp
, 14 + r
.ul
.x
, 49 + r
.ul
.y
);
1004 //--------------------------------------------------------------------------------------
1009 #define NANITE_Y 274
1013 void ShockHRMDraw(void)
1015 Rect r
= ShockOverlayGetRect(kOverlayHRM
);
1017 char temp
[255]; // ,fmtstr[64];
1018 ObjID o
= ShockOverlayGetObj();
1021 AutoAppIPtr(ShockPlayer
);
1022 AutoAppIPtr(GameStrings
);
1023 plr
= PlayerObject();
1026 DrawByHandle(gBackHnd
[gHRMMode
],r
.ul
);
1028 // draw the board state
1030 if (gHRMGameMode
!= kHRMModeNormal
)
1032 drawpt
.x
= MODE_X
+ r
.ul
.x
;
1033 drawpt
.y
= MODE_Y
+ r
.ul
.y
;
1034 DrawByHandle(gModeHnd
[gHRMGameMode
- 1][gHRMMode
], drawpt
);
1037 // draw in the main text
1039 mouse_get_xy(&mpt
.x
,&mpt
.y
);
1045 // short name up top
1046 if (ObjHasObjShortName(o))
1049 str = pGameStrings->FetchObjString(o,PROP_OBJSHORTNAME_NAME);
1051 gr_font_string(gShockFont,temp,r.ul.x + NAME_X, r.ul.y + NAME_Y);
1054 // and how many nanites we actually have
1058 sprintf(temp,"%d",ShockInvNaniteTotal());
1060 gr_font_string(gShockFont,temp,NANITE_X + r.ul.x, NANITE_Y + r.ul.y);
1063 // draw in the cost at the bottom
1064 //ShockStringFetch(fmtstr,sizeof(fmtstr),"Cost","hrm");
1065 sprintf(temp
,"%d",FindCost());
1067 w
= gr_font_string_width(gShockFont
, temp
);
1068 gr_font_string(gShockFont
,temp
,COST_X
+ r
.ul
.x
+ ((COST_W
- w
) / 2),COST_Y
+ r
.ul
.y
);
1070 // draw in the reset button
1071 if ((gHRMGameMode
!= kHRMModeWin
) && (gHRMGameMode
!= kHRMModeLose
))
1073 //LGadDrawBox(VB(&doit_button), NULL);
1075 pt
.x
= r
.ul
.x
+ DOIT_X
;
1076 pt
.y
= r
.ul
.y
+ DOIT_Y
;
1077 if (gHRMGameMode
== kHRMModeUnpaid
)
1078 DrawByHandle(doit_handles
[0],pt
);
1080 DrawByHandle(reset_handle
,pt
);
1084 LGadDrawBox(VB(&close_button
),NULL
);
1086 //--------------------------------------------------------------------------------------
1087 bool ShockHRMHandleMouse(Point pt
)
1091 if (RectTestPt(&board_rect
, pt
))
1093 // all these casts are probably excessive, but better safe than sorry
1094 x
= (float)(pt
.x
- board_rect
.ul
.x
) / (float)BOARD_DX
;
1095 y
= (float)(pt
.y
- board_rect
.ul
.y
) / (float)BOARD_DY
;
1096 // okay, now "round" so that we get the closest hit
1097 // the zany constant is because the node itself takes up about half the
1098 // size, so the remaining intervening space wants to be split in half
1099 loc
.x
= floor(x
+ 0.25);
1100 loc
.y
= floor(y
+ 0.25);
1101 ConfigSpew("hrm_spew",("piece loc %d, %d\n",loc
.x
,loc
.y
));
1102 if ((loc
.x
< 0) || (loc
.y
< 0) || (loc
.x
>= MATRIX_X
) || (loc
.y
>= MATRIX_Y
))
1105 if (gHRMGameMode
== kHRMModeNormal
)
1107 SchemaPlay((Label
*)"hacking",NULL
);
1113 //--------------------------------------------------------------------------------------
1114 void ShockHRMDisplay(ObjID o
, int mode
, BOOL use_psi
, int bonus
)
1116 if (ShockOverlayCheck(kOverlayHRM
))
1117 ShockOverlayChange(kOverlayHRM
, kOverlayModeOff
);
1122 gHRMGameMode
= kHRMModeUnpaid
;
1124 // check for skill zero and terminate
1127 AutoAppIPtr(ShockPlayer
);
1128 plr
= PlayerObject();
1132 skillval
= pShockPlayer
->GetTechSkill(FindSkill());
1138 ShockStringFetch(errmsg, sizeof(errmsg), "notechskill", "hrm", mode);
1139 ShockOverlayAddText(errmsg, DEFAULT_MSG_TIME);
1140 return; // dont even open the MFD
1146 if (g_ReqTechProperty
->Get(o
,&req
))
1147 reqval
= req
->m_tech
[FindSkill()];
1150 if (gHRMMode
== kTechModify
)
1152 int modlevel
= GunGetModification(o
);
1153 // second modification is harder
1155 reqval
= reqval
+ 2;
1157 if (skillval
< reqval
)
1159 char errmsg
[255],temp
[255];
1160 ShockStringFetch(errmsg
, sizeof(errmsg
), "techminskill", "hrm", mode
);
1161 sprintf(temp
,errmsg
,reqval
);
1162 ShockOverlayAddText(temp
, DEFAULT_MSG_TIME
);
1163 return; // dont even open the MFD
1166 // don't require softs anymore
1169 softobj = pShockPlayer->GetEquip(plr, FindSoftSlot());
1170 if (softobj == OBJ_NULL)
1173 ShockStringFetch(errmsg, sizeof(errmsg), "notechsoft", "hrm", mode);
1174 ShockOverlayAddText(errmsg, DEFAULT_MSG_TIME);
1175 return; // dont even open the MFD
1180 // if we are modifying but our weapon is already at max modification,
1181 // just give some feedback text
1184 int modlevel
= GunGetModification(o
);
1189 ShockStringFetch(errmsg
, sizeof(errmsg
), "ModifyResult3", "hrm");
1190 ShockOverlayAddText(errmsg
, DEFAULT_MSG_TIME
);
1191 return; // dont even open the MFD
1193 // these cases handle poking in the right difficulty property
1195 hrm_props
[2] = gPropModify2Diff
;
1198 hrm_props
[2] = gPropModifyDiff
;
1204 ShockOverlaySetDist(kOverlayHRM
, FALSE
);
1206 ShockOverlaySetDist(kOverlayHRM
, TRUE
);
1208 // okay, we've qualified so open the darned MFD
1209 ShockOverlayChange(kOverlayHRM
, kOverlayModeOn
);
1210 ShockOverlaySetObj(kOverlayHRM
, o
);
1217 // set up the initial jargon
1220 char temp
[255],temp2
[255];
1222 int statval
, softval
;
1223 int basediff
,chance
,mines
;
1227 if (!hrm_props
[gHRMMode
]->Get(o
,&ti
))
1233 param
= GetHRMParams();
1235 // base & final difficulty
1236 ShockStringFetch(temp2
,sizeof(temp2
),"JargonBaseDiff","jargon", gHRMMode
);
1237 basediff
= 100 - ti
->m_success
;
1238 sprintf(temp
,temp2
,basediff
);
1244 ShockStringFetch(temp2
,sizeof(temp2
),"JargonSkill","jargon", gHRMMode
);
1245 skillval
= pShockPlayer
->GetTechSkill(FindSkill());
1246 bonusval
= skillval
* param
->m_skillSuccessBonus
;
1247 sprintf(temp
,temp2
,skillval
,bonusval
);
1250 ShockStringFetch(temp2
,sizeof(temp2
),"JargonStat","jargon", gHRMMode
);
1251 statval
= pShockPlayer
->GetStat(kStatCyber
);
1252 bonusval
= statval
* param
->m_statSuccessBonus
;
1253 sprintf(temp
,temp2
,statval
,bonusval
);
1256 ShockStringFetch(temp2
,sizeof(temp2
),"JargonSoft","jargon", gHRMMode
);
1257 softval
= FindSoftLevel();
1260 bonusval
= (softval
) * param
->m_skillSuccessBonus
;
1261 sprintf(temp
,temp2
,softval
,bonusval
);
1265 if (pShockPlayer
->HasImplant(PlayerObject(), kImplantTech
) && !gHRMPsi
)
1267 ShockStringFetch(temp2
,sizeof(temp
),"JargonImplant","jargon", gHRMMode
);
1268 bonusval
= param
->m_skillSuccessBonus
;
1269 sprintf(temp
,temp2
,bonusval
);
1275 ShockStringFetch(temp2
,sizeof(temp2
),"JargonBonus","jargon", gHRMMode
);
1276 bonusval
= gHRMBonus
* param
->m_skillSuccessBonus
;
1277 sprintf(temp
,temp2
,bonusval
);
1283 ShockStringFetch(temp2
,sizeof(temp2
),"JargonSkill","jargon", gHRMMode
);
1284 skillval
= HRMSkill();
1285 bonusval
= skillval
* param
->m_skillSuccessBonus
;
1286 sprintf(temp
,temp2
,skillval
,bonusval
);
1289 ShockStringFetch(temp2
,sizeof(temp2
),"JargonStat","jargon", gHRMMode
);
1290 statval
= HRMStat(); // pShockPlayer->GetStat(kStatPsi);
1291 bonusval
= statval
* param
->m_statSuccessBonus
;
1292 sprintf(temp
,temp2
,statval
,bonusval
);
1296 ShockStringFetch(temp2,sizeof(temp2),"JargonPsiBonus","jargon", gHRMMode);
1297 sprintf(temp,temp2,gHRMBonus);
1302 ShockStringFetch(temp2
,sizeof(temp2
),"JargonFinalDiff","jargon", gHRMMode
);
1303 chance
= 100 - FindChance(ti
);
1304 sprintf(temp
,temp2
,chance
);
1308 mines
= FindMines(ti
);
1312 ShockStringFetch(temp2
,sizeof(temp2
),"JargonMinesOne","jargon", gHRMMode
);
1314 ShockStringFetch(temp2
,sizeof(temp2
),"JargonMines","jargon", gHRMMode
);
1315 sprintf(temp
,temp2
,mines
);
1318 //--------------------------------------------------------------------------------------
1319 static bool reset_cb(short action
, void* data
, LGadBox
* vb
)
1321 if (action
!= BUTTONGADG_LCLICK
)
1324 if ((gHRMGameMode
== kHRMModeWin
) || (gHRMGameMode
== kHRMModeLose
))
1329 SchemaPlay((Label
*)"start_hack",NULL
);
1331 // reset the state of the board
1335 gHRMGameMode
= kHRMModeNormal
;
1341 //--------------------------------------------------------------------------------------
1342 static bool close_cb(short action
, void* data
, LGadBox
* vb
)
1344 if (action
== BUTTONGADG_LCLICK
)
1346 uiDefer(DeferOverlayClose
,(void *)kOverlayHRM
);
1350 //--------------------------------------------------------------------------------------
1351 static void BuildInterfaceButtons(void)
1353 Rect r
= ShockOverlayGetRect(kOverlayHRM
);
1355 close_elem
.draw_type
= DRAWTYPE_BITMAPOFFSET
;
1356 close_elem
.draw_data
= close_bitmaps
;
1357 close_elem
.draw_data2
= (void *)4; // should be 2 but hackery required
1359 LGadCreateButtonArgs(&close_button
, LGadCurrentRoot(), close_rect
.ul
.x
+ r
.ul
.x
, close_rect
.ul
.y
+ r
.ul
.y
,
1360 RectWidth(&close_rect
), RectHeight(&close_rect
), &close_elem
, close_cb
, 0);
1362 doit_elem
.draw_type
= DRAWTYPE_BITMAPOFFSET
;
1363 doit_elem
.draw_data
= doit_bitmaps
;
1364 doit_elem
.draw_data2
= (void *)4; // should be 2 but hackery required
1366 LGadCreateButtonArgs(&doit_button
, LGadCurrentRoot(), doit_rect
.ul
.x
+ r
.ul
.x
, doit_rect
.ul
.y
+ r
.ul
.y
,
1367 RectWidth(&doit_rect
), RectHeight(&doit_rect
), &doit_elem
, reset_cb
, 0);
1370 //--------------------------------------------------------------------------------------
1371 static void DestroyInterfaceButtons(void)
1373 LGadDestroyBox(VB(&close_button
),FALSE
);
1374 LGadDestroyBox(VB(&doit_button
),FALSE
);
1376 //--------------------------------------------------------------------------------------
1377 void ShockHRMStateChange(int which
)
1379 if (ShockOverlayCheck(which
))
1381 // take down any plug-in that got us here
1382 ShockOverlayChange(kOverlayHRMPlug
, kOverlayModeOff
);
1383 BuildInterfaceButtons();
1387 DestroyInterfaceButtons();
1390 //--------------------------------------------------------------------------------------
1391 int ShockFindTechType(ObjID obj
)
1393 if (ObjGetObjState(obj
) == kObjStateUnresearched
)
1394 return(kTechResearch
);
1396 if ((ObjGetObjState(obj
) == kObjStateBroken
) && (gPropRepairDiff
->IsRelevant(obj
)))
1397 return(kTechRepair
);
1399 if (IsPlayerGun(obj
) && gPropModifyDiff
->IsRelevant(obj
))
1400 return(kTechModify
);
1402 if (gPropHackDiff
->IsRelevant(obj
))
1403 return(kTechHacking
);
1407 //--------------------------------------------------------------------------------------
1408 sOverlayFunc OverlayHRM
= {
1409 ShockHRMDraw
, // draw
1410 ShockHRMInit
, // init
1411 ShockHRMTerm
, // term
1412 ShockHRMHandleMouse
, // mouse
1413 NULL
, // dclick (really use)
1418 "subpanel_cl", // downschema
1419 ShockHRMStateChange
, // state
1420 NULL
, // transparency
1424 NULL
, // update func
1425 TRUE
, // check contains?