2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // Deep Cover specific game features
22 // ActReact enhancments.
103 #include <netsynch.h>
108 #include <osysbase.h>
109 #include <objquery.h>
113 #include <lnkquery.h>
115 #include <linkbase.h>
116 #include <relation.h>
117 #include <traitman.h>
118 #include <dpclinks.h>
119 #include <dpcobjst.h>
120 #include <objlpars.h>
129 #include <physcast.h>
140 #include <objlight.h>
143 #include <particle.h>
144 #include <partprop.h>
148 #include <rendprop.h>
149 #include <mnamprop.h>
150 #include <dpccmapi.h>
151 #include <dpcrend.h> // for pick reset
152 #include <dpccobpr.h>
155 #include <scrnovls.h>
156 #include <scrnmode.h>
157 #include <anim_txt.h>
158 #include <creature.h>
159 #include <scrptapi.h>
160 #include <scrptmsg.h>
161 #include <dpcscapi.h>
167 #include <simstate.h>
168 #include <drkbreth.h>
173 #include <dpcsndpr.h>
174 #include <dpcsound.h>
182 #include <dpccurm.h> // For SCM modes
186 #include <dpcinvpr.h>
187 #include <dpciface.h>
188 #include <dpccurpr.h>
190 #include <dpcoptmn.h>
191 #include <dpclding.h>
192 #include <dpcmulti.h>
193 #include <dpcsavui.h>
194 #include <dpcovrly.h>
195 #include <dpcovcst.h>
196 #include <dpcemail.h>
200 #include <prjctile.h>
202 #include <dpcammov.h>
205 #include <dpcpgapi.h>
207 // Dark tools & other loot
209 #include <drkbreth.h>
220 // Other Deep Cover files
223 #include <dpcutils.h>
224 #include <dpcblood.h>
226 #include <dpcreprt.h>
228 #include <drkuires.h>
229 #include <globalid.h>
230 #include <transmod.h>
231 #include <dpcincst.h>
234 #include <dpccmapi.h>
241 #define USE_DIST 100.0F
243 // is the user typing a message
244 static bool typingMode
=FALSE
;
246 static Point gLastpos
= {-1,-1};
248 bool DPC_mouse
= FALSE
;
252 int DPC_cursor_mode
= SCM_NORMAL
;
254 extern Rect gun_rect
;
255 static Rect power_rect
= {{276,254}, {447,390}};
256 static Rect subpower_rect
= {{456,254}, {629,390}};
257 ObjID drag_obj
= OBJ_NULL
; // what is ON the cursor
258 bool DPC_mouse_loaded
= FALSE
; // have we loaded in cursor art yet?
260 // controllers in dark for focus/actions
261 BOOL active_focus
=FALSE
;
262 BOOL world_use_in_progress
=FALSE
;
265 void CameraPositionSpew(void);
268 void DPCDrawCursor(Point pt
)
270 // don't allow anything if player dead
271 if (GetPlayerMode() == kPM_Dead
)
274 // now, depending on cursor mode, draw some help text
278 short dx
, dy
, w
, bmh
;
280 // the easy part: draw the art
281 if (gCursorHnd
== gDefaultHnd
)
282 DrawCursorByHandle(gCursorHnd
,pt
); // we should probably decide this a better way....
284 DrawCursorByHandleCenter(gCursorHnd
,pt
);
286 AutoAppIPtr(GameStrings
);
287 useobj
= frobWorldSelectObj
;
288 if (useobj
== OBJ_NULL
)
289 useobj
= g_ifaceFocusObj
;
290 if (useobj
== OBJ_NULL
)
294 AutoAppIPtr(DPCCamera
);
295 if (pDPCCamera
->GetEditMode() != kCameraNormal
)
301 AutoAppIPtr(ContainSys
);
304 switch (DPC_cursor_mode
)
307 // okay, if the object we are over is a world object, use it's world text.
308 if (useobj
== frobWorldSelectObj
)
310 str
= pGameStrings
->FetchObjString(useobj
, PROP_WORLDCURSOR_NAME
);
312 // otherwise, use its inventory text
315 str
= pGameStrings
->FetchObjString(useobj
, PROP_INVCURSOR_NAME
);
317 cont
= pContainSys
->GetContainer(useobj
);
318 if ((cont
== OBJ_NULL
) || (cont
== PlayerObject()))
327 if (strlen(temp
) == 0)
330 w
= gr_font_string_width(gDPCFont
, temp
);
331 bmh
= 16; // rather than compute
336 if (dx
+ w
+ 10 > smode
.w
)
337 dx
= smode
.w
- w
- 10;
340 dy
= pt
.y
+ (bmh
/ 2) + 2;
342 gr_set_fcolor(gDPCTextColor
);
343 gr_font_string(gDPCFontMono
, temp
, dx
, dy
);
346 static void doMouseFocusCheck(void)
351 mouse_get_xy(&mx
,&my
);
352 mpt
.x
= mx
; mpt
.y
= my
;
353 occlude
= DPCOverlayMouseOcclude(mpt
);
355 // timeout any "stale" focus items
357 g_ifaceFocusObj
= OBJ_NULL
;
358 gFocusTouched
= FALSE
;
360 if ((frobWorldSelectObj
== OBJ_NULL
) || (frobWorldSelectObj
!= g_PickCurrentObj
) || occlude
)
363 if (gPropHUDTime
->Get(frobWorldSelectObj
,&t
))
366 gPropHUDTime
->Delete(frobWorldSelectObj
);
369 if ((g_PickCurrentObj
!= OBJ_NULL
) && (!occlude
))
371 if (frobWorldSelectObj
!= g_PickCurrentObj
)
374 if ((gPropAllowHUDSelect
->Get(g_PickCurrentObj
,&showhud
)) && showhud
)
376 gPropHUDTime
->Set(g_PickCurrentObj
, 0);
377 DPCInterfaceMouseOver(g_PickCurrentObj
);
380 frobWorldSelectObj
= g_PickCurrentObj
;
384 frobWorldSelectObj
= OBJ_NULL
;
387 // bonus space for cursors and such
389 static char typebuf
[TYPE_MAX
+3];
393 EXTERN
int hack_for_kbd_state(void);
394 #define CTRL_STATES (KBM_LCTRL|KBM_RCTRL)
396 bool MouseMode(bool mode
, bool clear
)
399 AutoAppIPtr(QuestData
);
400 slim_mode
= pQuestData
->Get("HideInterface");
402 // don't allow into into cursor mode if we are pre-HUD
403 if (mode
&& slim_mode
)
406 // don't allow out of mouse mode if object on cursor
407 if (!mode
&& DPC_mouse
&& (drag_obj
!= OBJ_NULL
))
411 DPCOverlayMouseMode(mode
);
416 InstallIBHandler (HK_GAME2_MODE
, UI_EVENT_KBD_RAW
| UI_EVENT_MOUSE
| UI_EVENT_MOUSE_MOVE
| UI_EVENT_JOY
, FALSE
);
418 //dont let input binding sys process mouse move events
419 headmoveSetRelPosX(0);
420 headmoveSetRelPosY(0);
421 g_pInputBinder
->SetValidEvents (ALL_EVENTS
& (~UI_EVENT_MOUSE_MOVE
)); // & (~UI_EVENT_MOUSE));
423 if (!DPC_mouse_loaded
)
425 gDefaultHnd
= DPC_mouse_hnd
= LoadPCX("cursor"); // , INTERFACE_PATH, DPCLoadNoPalette);
426 DPC_mouse_loaded
= TRUE
;
428 SetCursorByHandle(DPC_mouse_hnd
);
430 if (gLastpos
.x
!= -1)
431 mouse_put_xy(gLastpos
.x
,gLastpos
.y
);
438 InstallIBHandler (HK_GAME_MODE
, UI_EVENT_KBD_RAW
| UI_EVENT_MOUSE
| UI_EVENT_MOUSE_MOVE
| UI_EVENT_JOY
, FALSE
);
439 //turn input binder's mouse move events back on
440 g_pInputBinder
->SetValidEvents (ALL_EVENTS
); // & (~UI_EVENT_MOUSE));
443 mouse_get_xy(&gLastpos
.x
,&gLastpos
.y
);
446 centerx
= smode
.w
/ 2; //grd_visible_canvas->bm.w / 2;
447 centery
= smode
.h
/ 2; //grd_visible_canvas->bm.h / 2;
448 //mprintf("center = %d, %d\n",centerx,centery);
450 // What the heck was this doing? this is certain to cause whiplash on inv mode changes!
451 // removed, 6/9/99 Xemu
454 mouse_put_xy(centerx
, centery
);
455 // clear out HUD selection rectangle
456 if (frobWorldSelectObj
!= OBJ_NULL
)
459 if (gPropHUDTime
->Get(frobWorldSelectObj
, &t
) && (t
== 0))
460 gPropHUDTime
->Delete(frobWorldSelectObj
);
463 frobWorldSelectObj
= OBJ_NULL
;
464 if (DPC_mouse_loaded
)
466 SafeFreeHnd(&DPC_mouse_hnd
);
467 DPC_mouse_loaded
= FALSE
;
472 // make sure nothing gets stuck down
473 //g_pInputBinder->PollAllKeys();
478 void DPC_check_keys(void)
480 //static bool last_ctrl = FALSE;
483 int kb_mods=hack_for_kbd_state();
484 //bool old_mouse = DPC_mouse;
485 bool ctrl_down = (kb_mods & CTRL_STATES);
486 static bool ctrl_used = FALSE;
489 if (DPC_cursor_mode == SCM_NORMAL)
497 if (DPC_cursor_mode == SCM_LOOK)
509 #pragma off(unreferened)
510 bool DPC_key_parse(int keycode
)
514 // MFDs and other overlaid interface elements
515 if (keycode
&KB_FLAG_DOWN
)
516 if (DPCOverlayHandleKey(keycode
))
519 // camera recording mode
520 AutoAppIPtr(DPCCamera
);
521 if (pDPCCamera
->GetEditMode() == kCameraRecord
)
522 return DPCControlKeyParse(keycode
, pDPCCamera
->GetAttachObject(), pDPCCamera
->GetCameraSpeed());
524 if (pDPCCamera
->GetEditMode() == kCameraEdit
)
526 if (!(keycode
&KB_FLAG_DOWN
))
529 kc
=keycode
&~KB_FLAG_DOWN
;
533 SetSimTimePassing(!IsSimTimePassing());
544 pDPCCamera
->SwitchCamera(kc
-'1');
547 pDPCCamera
->SwitchCamera(10);
553 if (keycode
&KB_FLAG_DOWN
)
555 kc
=keycode
&~KB_FLAG_DOWN
;
558 //case 'w': g_playerMoveMode = kPlayerRun; return FALSE;
559 //case 's': g_playerMoveMode = kPlayerWalk; return FALSE;
560 //case 'x': g_playerMoveMode = kPlayerBackup; return FALSE;
578 case 'w': g_playerMoveMode = kPlayerMoveNone; return FALSE;
579 case 's': g_playerMoveMode = kPlayerMoveNone; return FALSE;
580 case 'x': g_playerMoveMode = kPlayerMoveNone; return FALSE;
591 // Throwing an object back into the world. This is a little complex,
592 // because if this is a multiuser game, then we have to hand the object
593 // back to the world host.
596 static cNetMsg
*g_pThrowObjMsg
= NULL
;
599 // This code should only be run on the world host, and deals with actually
600 // putting the object back into the world:
602 static void handleThrowObj(ObjID obj
, ObjID src
)
604 // Take the object back from the thrower:
605 AutoAppIPtr(NetManager
);
606 if (pNetManager
->IsNetworkGame())
608 AutoAppIPtr(ObjectNetworking
);
609 pObjectNetworking
->ObjTakeOver(obj
);
612 // Try to deal with throwing out a melee weapon that is still
613 // animating its close
614 AutoAppIPtr(DPCPlayer
);
615 if (IsMelee(obj
) && IsCurrentPlayerArm(obj
))
616 PlayerSwitchMode(kPlayerModeInvalid
);
618 ObjPos
*pos
= ObjPosGet(src
);
619 mxs_vector plrpos
, dir
;
621 mxs_matrix mat
; // There is no spoon, only the matrix
623 mx_copy_vec(&plrpos
,&pos
->loc
.vec
);
625 // Place the object at the player's location, so networking has a more
626 // or less rational start position for the thing:
627 ObjPosCopyUpdate(obj
, pos
);
629 ObjSetHasRefs(obj
,TRUE
);
630 PhysRegisterSphereDefault(obj
);
632 sGameParams
*params
= GetGameParams();
633 int randval
= Rand() % 100;
636 if (config_is_defined("disable_random_throw"))
637 power
= params
->throwpower
;
639 power
= params
->throwpower
* (0.9 + (0.2 * (float(randval
) / 100)));
641 // get player angle, and disturb it a touch
642 memcpy(&plrang
,&pos
->fac
,sizeof(mxs_angvec
));
644 if (!config_is_defined("disable_random_throw"))
645 plrang
.tz
+= (Rand() % 0x0A00) - 0x0500;
646 mx_ang2mat(&mat
,&plrang
);
648 // set our final throw direction in world coords
649 mx_copy_vec(&dir
,&mat
.vec
[0]);
651 if (launchProjectile(src
,obj
,power
,PRJ_FLG_PUSHOUT
|PRJ_FLG_MASSIVE
|PRJ_FLG_NO_FIRER
,NULL
,&dir
,NULL
) == OBJ_NULL
)
653 // Head too close to some surface, launch from body instead
655 mx_copy_vec(&loc
, &ObjPosGet(src
)->loc
.vec
);
657 launchProjectile(src
,obj
,power
,PRJ_FLG_PUSHOUT
|PRJ_FLG_MASSIVE
|PRJ_FLG_NO_FIRER
,NULL
,&dir
,&loc
);
659 PhysNetBroadcastObjPosByObj(obj
);
662 static sNetMsgDesc sThrowObjDesc
=
666 "Throw Object Back to World",
669 {{kNMPT_SenderObjID
, kNMPF_None
, "Obj"},
670 {kNMPT_SenderObjID
, kNMPF_None
, "From"},
675 // Tell the default host that we're throwing the object back to the world
678 void ThrowObj(ObjID o
, ObjID src
)
680 // If the host is throwing the thing, then this will just loop back
681 // and land in handleThrowObj:
682 g_pThrowObjMsg
->Send(OBJ_NULL
, o
, src
);
684 // And now, the object is no longer on our cursor.
687 DPCInvLoadCursor(OBJ_NULL
);
693 // player is interacting with the interface / frobbing
694 void DPCInterfaceUseItem()
696 // don't allow anything if player dead
697 if (GetPlayerMode() == kPM_Dead
)
700 if (DPC_cursor_mode
== SCM_LOOK
)
707 mouse_get_xy(&pos
.x
, &pos
.y
);
709 // kind of a misnomer now, since doubleclicks are gone
710 DPCOverlayDoubleClick(pos
);
715 // player wants to change mode with no other effects
718 // don't allow anything if player dead
719 if (GetPlayerMode() == kPM_Dead
)
721 MouseMode(!DPC_mouse
,TRUE
);
724 // toggle mode, first frobbing what is under the cursor
727 // don't allow anything if player dead
728 if (GetPlayerMode() == kPM_Dead
)
733 void DPCFrobObjectInv()
735 // don't allow anything if player dead
736 if (GetPlayerMode() == kPM_Dead
)
738 // if we have a world object, frob it
739 if (frobWorldSelectObj
!= OBJ_NULL
)
743 // otherwise, inv-frob
746 DPCInterfaceUseItem();
750 void DPCFrobAndMaybeToggleMode() // BOOL start
752 // don't allow anything if player dead
753 if (GetPlayerMode() == kPM_Dead
)
755 // only do stuff on the downs
759 if (frobWorldSelectObj
== OBJ_NULL
)
761 if (DPC_cursor_mode
== SCM_NORMAL
)
762 MouseMode(!DPC_mouse
, TRUE
);
767 BOOL switchmode
= FALSE
;
769 if (DPC_cursor_mode
== SCM_DRAGOBJ
)
775 // if the object we are trying to frob has no relevant
776 // frob engine properties, then allow a switch
777 AutoAppIPtr(ObjectSystem
);
778 if (pObjectSystem
->Exists(frobWorldSelectObj
))
781 if (!pFrobInfoProp
->Get(frobWorldSelectObj
, &frobinfo
))
783 else if (frobinfo
->actions
[kFrobLocWorld
] == 0)
790 MouseMode(!DPC_mouse
, TRUE
);
795 void DPCHilightObject()
797 AutoAppIPtr(NetManager
);
798 if (!pNetManager
->Networking())
799 // This feature only really makes sense in multiplayer
802 if ((frobWorldSelectObj
!= OBJ_NULL
) && ObjHasRefs(frobWorldSelectObj
))
804 DPCBroadcastHilightObject(frobWorldSelectObj
);
812 BOOL
DPCInterfaceClick()
814 // Don't allow anything if player dead
815 if (GetPlayerMode() == kPM_Dead
)
822 mouse_get_xy(&pos
.x
, &pos
.y
);
824 if (DPCOverlayClick(pos
)) // interface hacks
829 switch (DPC_cursor_mode
)
833 BOOL throw_me
= FALSE
;
834 if (frobWorldSelectObj
== OBJ_NULL
)
840 frobInvSelectObj
= frobWorldSelectObj
; // set the target of the tool frob
843 if (DPCScriptAllowSwap())
848 if (throw_me
&& (drag_obj
!= OBJ_NULL
))
851 ThrowObj(drag_obj
,PlayerObject());
861 if (frobWorldSelectObj != OBJ_NULL)
863 DPCLookPopup(frobWorldSelectObj);
875 static void DPCFireWeapon(BOOL start
)
877 if (GetPlayerMode() == kPM_Dead
)
879 // removed 5/31/99: Xemu
881 // finish dying, that is to say, unwind or resurrect
882 AutoAppIPtr(ScriptMan);
883 sScrMsg msg(PlayerObject(),"FinishDying");
884 msg.flags |= kSMF_MsgPostToOwner;
885 pScriptMan->SendMessage(&msg);
889 //mprintf("firing weapon!\n");
891 // no firing if no interface
892 AutoAppIPtr(QuestData
);
893 BOOL slim_mode
= pQuestData
->Get("HideInterface");
899 AutoAppIPtr(PlayerGun
);
900 AutoAppIPtr(DPCPlayer
);
904 if (pPlayerGun
->Get() != OBJ_NULL
)
906 pPlayerGun
->PullTrigger();
908 StartMeleeAttack(PlayerObject(), GetWeaponObjID(PlayerObject()));
912 if (pPlayerGun
->Get() != OBJ_NULL
)
914 pPlayerGun
->ReleaseTrigger();
916 FinishMeleeAction(PlayerObject(), GetWeaponObjID(PlayerObject()));
921 static void DPCQueryMode(BOOL start
)
923 // don't allow anything if player dead
924 if (GetPlayerMode() == kPM_Dead
)
928 if (DPC_cursor_mode
== SCM_NORMAL
)
933 if (DPC_cursor_mode
== SCM_LOOK
)
938 static void DPCSplitMode(BOOL start
)
940 // don't allow anything if player dead
941 if (GetPlayerMode() == kPM_Dead
)
945 if (DPC_cursor_mode
== SCM_NORMAL
)
952 if (DPC_cursor_mode
== SCM_SPLIT
)
964 static void DPCDragDropCore(BOOL start
, int func
)
966 // don't allow anything if player dead
967 if (GetPlayerMode() == kPM_Dead
)
970 mouse_get_xy(&pos
.x
, &pos
.y
);
974 if (DPCOverlayDragDrop(pos
, start
))
979 int oldmode
= DPC_cursor_mode
;
981 if (DPCOverlayDragDrop(pos
, start
))
984 if ((DPC_cursor_mode
!= SCM_NORMAL
) || (oldmode
!= SCM_NORMAL
))
993 MouseMode(!DPC_mouse
,TRUE
);
999 static void DPCDragDropFrob(BOOL start
)
1001 DPCDragDropCore(start
, DDFROB
);
1004 static void DPCDragDropSimple(BOOL start
)
1006 DPCDragDropCore(start
, DDNONE
);
1009 static void DPCDragDropMode(BOOL start
)
1011 DPCDragDropCore(start
, DDMODE
);
1014 static void DPCToggleInv(void)
1016 DPCOverlayChange(kOverlayInv
, kOverlayModeToggle
);
1019 static void DPCToggleCompass(void)
1021 AutoAppIPtr(DPCPlayer
);
1022 AutoAppIPtr(ScriptMan
);
1023 ObjID compass
= pDPCPlayer
->GetEquip(PlayerObject(),kEquipCompass
);
1024 if (compass
== OBJ_NULL
)
1029 // don't allow the compass to be turned on until
1030 // we have the interface "installed"
1032 AutoAppIPtr(QuestData
);
1033 slim_mode
= pQuestData
->Get("HideInterface");
1039 sScrMsg
msg(compass
,"Toggle");
1040 pScriptMan
->SendMessage(&msg
);
1043 static void DPCCycleAmmo(void)
1045 DPCAmmoChangeTypes();
1048 static void DPCSettingToggle(ObjID gun
)
1051 //AutoAppIPtr(PlayerGun);
1052 AutoAppIPtr(DPCPlayer
);
1053 AutoAppIPtr(TraitManager
);
1054 AutoAppIPtr(ObjectSystem
);
1056 //ObjID gun = pPlayerGun->Get();
1057 if (gun
== OBJ_NULL
)
1062 g_pWeaponTypeProperty
->Get(gun
,&wpntype
);
1064 // on a melee weapon, do nothing at all
1065 if (g_pMeleeTypeProperty
->IsRelevant(gun
))
1068 AutoAppIPtr(ContainSys
);
1069 // First unapply a meta prop if we have an applied one
1070 const char *metaName
= GetWeaponModeUnchangeMetaProp(gun
);
1073 ObjID metaProp
= pObjectSystem
->GetObjectNamed(metaName
);
1076 pTraitManager
->RemoveObjMetaProperty(gun
, metaProp
);
1078 int newloc
= pContainSys
->IsHeld(PlayerObject(),gun
);
1079 pDPCPlayer
->Equip(PlayerObject(), kEquipWeapon
, gun
, FALSE
);
1080 pContainSys
->Add(PlayerObject(), gun
, newloc
, CTF_NONE
);
1082 //pDPCPlayer->Equip(PlayerObject(), kEquipWeapon, gun, FALSE);
1087 const char *metaName
= GetWeaponModeChangeMetaProp(gun
);
1090 ObjID metaProp
= pObjectSystem
->GetObjectNamed(metaName
);
1093 pTraitManager
->AddObjMetaProperty(gun
, metaProp
);
1095 int newloc
= pContainSys
->IsHeld(PlayerObject(),gun
);
1096 pDPCPlayer
->Equip(PlayerObject(), kEquipWeapon
, gun
, FALSE
);
1097 pContainSys
->Add(PlayerObject(), gun
, newloc
, CTF_NONE
);
1099 //pDPCPlayer->Equip(PlayerObject(), kEquipWeapon, gun, FALSE);
1106 int curmode
= GunGetSetting(gun
);
1107 int numModes
= BaseGunDescGetNumSettings(gun
);
1109 curmode
= (curmode
+1) % numModes
;
1110 GunSetSetting(gun
,curmode
);
1112 float zoom
= BaseGunDescGetZoom(gun
);
1113 ZoomTarget(zoom
, 2.0);
1116 char temp
[255], fmt
[255];
1117 extern char *setting_headlines
[2]; // hack
1119 AutoAppIPtr(GameStrings
);
1120 cStr str
= pGameStrings
->FetchObjString(gun
, setting_headlines
[!curmode
]);
1121 DPCStringFetch(fmt
,sizeof(fmt
), "SettingChange", "misc");
1122 sprintf(temp
,fmt
,str
);
1123 DPCOverlayAddText(temp
,DEFAULT_MSG_TIME
);
1127 #define MAX_EQUIP_CANDIDATES 64
1129 static int equip_val(ObjID o
)
1131 // basically, return the condition
1132 int retval
= 0 - (GunGetCondition(o
) * 100);
1134 // out of ammo is bad
1135 if (GunStateGetAmmo(o
) == 0)
1137 retval
= retval
+ 10000;
1140 // introduce a minor objID element so that there are fewer/no ties
1141 retval
= retval
+ (o
% 100);
1146 static int equip_compare(const void *p
, const void *q
)
1148 ObjID
*a
= (ObjID
*) p
;
1149 ObjID
*b
= (ObjID
*) q
;
1151 if (equip_val(*b
) > equip_val(*a
))
1153 return(equip_val(*b
) < equip_val(*a
));
1156 static void DPCUseObj(char *args
)
1158 AutoAppIPtr(ContainSys
);
1159 AutoAppIPtr(ObjectSystem
);
1160 AutoAppIPtr(TraitManager
);
1162 // no hotkey usage if dead
1163 if (GetPlayerMode() == kPM_Dead
)
1168 // no hotkey usage if no interface
1169 AutoAppIPtr(QuestData
);
1170 BOOL slim_mode
= pQuestData
->Get("HideInterface");
1177 ObjID arch
= pObjectSystem
->GetObjectNamed(args
);
1179 sContainIter
*iterp
= pContainSys
->IterStart(PlayerObject());
1180 while (!iterp
->finished
)
1182 invobj
= iterp
->containee
;
1184 // Use it as if double clicked in inventory
1185 if (pTraitManager
->ObjHasDonor(invobj
, arch
))
1187 frobInvSelectObj
= invobj
;
1189 pContainSys
->IterEnd(iterp
);
1194 pContainSys
->IterNext(iterp
);
1196 pContainSys
->IterEnd(iterp
);
1201 DPCStringFetch(fmt
, sizeof(fmt
), "NotInInventory", "misc");
1202 AutoAppIPtr(GameStrings
);
1203 cStr str
= pGameStrings
->FetchObjString(arch
, PROP_OBJSHORTNAME_NAME
);
1204 sprintf(temp
, fmt
, str
);
1205 DPCOverlayAddText(temp
,DEFAULT_MSG_TIME
);
1208 static BOOL
DPCWeaponEquipCore(char *args
, BOOL spew
)
1210 // search the player's inventory for a matching weapon
1211 // args can now be NULL meaning unequip only
1213 ObjID candidates
[MAX_EQUIP_CANDIDATES
];
1214 eContainType newloc
;
1219 AutoAppIPtr(PlayerGun
);
1220 AutoAppIPtr(ContainSys
);
1221 AutoAppIPtr(ObjectSystem
);
1222 AutoAppIPtr(TraitManager
);
1223 AutoAppIPtr(DPCPlayer
);
1224 AutoAppIPtr(QuestData
);
1226 // dont switch if no interface
1227 BOOL slim_mode
= pQuestData
->Get("HideInterface");
1233 // don't switch if we are dead
1234 if (GetPlayerMode() == kPM_Dead
)
1239 // don't do jack if we are in the middle of reloading
1240 if (pPlayerGun
->IsReloading())
1245 // dont let you switch weapons mid firing
1246 ObjID gun
= pPlayerGun
->Get();
1247 if ((gun
!= OBJ_NULL
) && pPlayerGun
->IsTriggerPulled())
1252 ObjID playerobj
= PlayerObject();
1253 ObjID newobj
= OBJ_NULL
;
1254 ObjID prevobj
= pDPCPlayer
->GetEquip(playerobj
, kEquipWeapon
);
1258 // Just unequipping, thanks
1259 if (IsMelee(prevobj
)) {
1260 pDPCPlayer
->Equip(playerobj
, kEquipWeapon
, OBJ_NULL
,spew
);
1261 DPCInvAddObj(playerobj
, prevobj
, 1);
1263 ZoomTarget(1.0, 0.0);
1265 // Lower gun then unequip in player gun code
1266 pPlayerGun
->Unequip(prevobj
, OBJ_NULL
, spew
, TRUE
);
1276 ObjID weaparch
= pObjectSystem
->GetObjectNamed(args
);
1277 // bail out if the request object doesn't exist
1278 if (weaparch
== OBJ_NULL
)
1281 for (i
=0; i
< MAX_EQUIP_CANDIDATES
; i
++)
1283 candidates
[i
] = OBJ_NULL
;
1286 BOOL currentIsThisKind
= FALSE
;
1287 sContainIter
*iterp
= pContainSys
->IterStart(playerobj
);
1288 while (args
&& !iterp
->finished
)
1290 invobj
= iterp
->containee
;
1293 if (pTraitManager
->ObjHasDonor(invobj
, weaparch
))
1295 if (invobj
!= prevobj
)
1302 currentIsThisKind
= TRUE
;
1308 eObjState st
= ObjGetObjState(invobj
);
1309 if (st
== kObjStateNormal
)
1311 candidates
[count
] = invobj
;
1313 // abort out if somehow we have more objects than we can contemplate
1314 if (count
== MAX_EQUIP_CANDIDATES
)
1320 pContainSys
->IterNext(iterp
);
1322 pContainSys
->IterEnd(iterp
);
1324 // if we have no canditates, punt
1325 if (count
== 0 && args
)
1327 if (currentIsThisKind
) {
1328 // User hit '2' when a weapon '2' is equipped (for instance)
1329 // which means -- toggle the setting!
1330 DPCSettingToggle(prevobj
);
1336 // sort the candidates by quality
1337 qsort(candidates
, count
, sizeof(candidates
[0]), equip_compare
);
1339 // if we have no previous considerations, take the first (best)
1340 if ((prevobj
== OBJ_NULL
) || (!pTraitManager
->ObjHasDonor(prevobj
, weaparch
)))
1342 newobj
= candidates
[0];
1346 // we want the candidate which is closest above our current object
1347 for (i
=0; i
< count
; i
++)
1349 if (equip_val(candidates
[i
]) > equip_val(prevobj
))
1351 newobj
= candidates
[i
];
1355 // if there are none, take the first
1356 if (newobj
== OBJ_NULL
)
1358 newobj
= candidates
[0];
1363 // okay, do the swap
1364 if (newobj
!= OBJ_NULL
)
1366 if (pDPCPlayer
->CheckRequirements(newobj
, spew
))
1370 if (IsMelee(prevobj
))
1372 // first unequip the old thing
1373 newloc
= pContainSys
->IsHeld(playerobj
,newobj
);
1374 pDPCPlayer
->Equip(playerobj
, kEquipWeapon
, newobj
, spew
);
1375 pContainSys
->Add(playerobj
, prevobj
, newloc
, CTF_NONE
);
1380 ZoomTarget(1.0, 0.0);
1382 // Lower gun then unequip in player gun code
1383 pPlayerGun
->Unequip(prevobj
, newobj
, spew
, TRUE
);
1388 pDPCPlayer
->Equip(playerobj
, kEquipWeapon
, newobj
, spew
);
1397 static void DPCWeaponEquip(char *args
)
1399 DPCWeaponEquipCore(args
, TRUE
);
1402 static void DPCWeaponUnequip(void)
1404 DPCWeaponEquipCore(NULL
, TRUE
);
1407 static void DPCWeaponUnjam(void)
1409 AutoAppIPtr(DPCPlayer
);
1411 ObjID playerobj
= PlayerObject();
1412 ObjID gunobj
= pDPCPlayer
->GetEquip(playerobj
, kEquipWeapon
);
1414 int state
= ObjGetObjState(gunobj
);
1415 if (state
== kObjStateBroken
) {
1416 int skillval
= pDPCPlayer
->GetTechSkill(kTechRepair
);
1417 // skillval goes 0 to ...6?...
1418 if (Rand() % 6 < skillval
) {
1420 ObjSetObjState(gunobj
, kObjStateNormal
);
1421 SchemaPlay((Label
*)"unjam",NULL
);
1424 SchemaPlay((Label
*)"unjam_fail",NULL
);
1429 static char *weapon_order
[] =
1431 "psi amp", "wrench", "pistol", "shotgun", "assault rifle",
1432 "laser pistol", "EMP Rifle", "Electro Shock", "Gren Launcher", "Stasis Field Generator",
1433 "Fusion Cannon", "Crystal Shard", "Viral Prolif", "Worm Launcher",
1436 #define WEAPON_CYCLE (sizeof(weapon_order) / sizeof(char *))
1437 static void DPCWeaponCycle(int dir
)
1444 AutoAppIPtr(DPCPlayer
);
1445 AutoAppIPtr(TraitManager
);
1446 AutoAppIPtr(ObjectSystem
);
1448 // find the currently equipped weapon
1449 ObjID current
= pDPCPlayer
->GetEquip(PlayerObject(), kEquipWeapon
);
1450 if (current
== OBJ_NULL
)
1456 weaparch
= pTraitManager
->GetArchetype(current
);
1457 strcpy(archname
, pObjectSystem
->GetName(weaparch
));
1459 for (i
=0; i
< WEAPON_CYCLE
; i
++)
1461 //mprintf("comparing %s to %s\n",archname, weapon_order[i]);
1462 if (stricmp(archname
,weapon_order
[i
]) == 0)
1471 while (count
< WEAPON_CYCLE
)
1474 // try to equip this type of weapon
1475 if (num
== WEAPON_CYCLE
)
1481 num
= WEAPON_CYCLE
- 1;
1483 if (DPCWeaponEquipCore(weapon_order
[num
], FALSE
))
1485 count
= WEAPON_CYCLE
;
1491 static void HackFOVCompute(void)
1495 mxs_angvec av1
, av2
;
1496 r3_get_view_pyr_vecs(vecs
);
1498 mxs_vector
*v1
= &vecs
[0];
1499 mxs_vector
*v2
= &vecs
[2];
1501 // take the view pyramid and turn it into angvecs
1502 // by first converting into a rotation matrix
1503 mx_mk_move_x_mat(&m1
, v1
);
1504 mx_mk_move_x_mat(&m2
, v2
);
1506 // then deconstructing that
1507 mx_mat2ang(&av1
, &m1
);
1508 mx_mat2ang(&av2
, &m2
);
1510 //mprintf ("v1 = %g, %g, %g v2 = %g, %g, %g \n",av1.el[0],av1.el[1],av1.el[2],av2.el[0],av2.el[1],av2.el[2]);
1511 //mprintf ("delta = %g %g %g\n",av1.el[0] - av2.el[0],av1.el[1] - av2.el[1],av1.el[2] - av2.el[2]);
1514 #pragma on(unreferenced)
1516 // per frame updates, for now just spells
1517 // #define PICK_DIST 35
1518 void DPC_sim_update_frame(int ms
)
1520 ectsAnimTxtTime
=GetSimTime();
1521 ectsAnimTxtUpdateAll();
1524 mouse_get_xy(&mpt
.x
,&mpt
.y
);
1526 headmoveCheck(PlayerCamera(),ms
);
1527 playerHeadControl();
1529 doMouseFocusCheck();
1531 sGameParams
*params
= GetGameParams();
1534 // set focus way out for non-cursor mode
1535 //PickSetFocus(fix_make(mpt.x, 0), fix_make(mpt.y, 0), 10000);
1538 ScrnModeGet(&smode
);
1540 PickSetFocus(fix_make(smode
.w
/ 2,0),fix_make(smode
.h
/ 2,0),params
->frobdist
);
1541 //PickSetFocus(fix_make(smode.w / 2,0),fix_make(smode.h / 2,0),64);
1543 //doHeadFocusCheck();
1548 PickSetFocus(fix_make(mpt
.x
, 0), fix_make(mpt
.y
, 0), params
->frobdist
);
1552 // Jon: what is this doing?
1553 // Xemu: I think this is intended for checking object consistency per frame and whatnot
1555 IObjectQuery* pQuery;
1556 IObjectSystem* pOS = AppGetObj(IObjectSystem);
1558 pQuery = IObjectSystem_Iter(pOS, kObjectConcrete);
1559 for (; !IObjectQuery_Done(pQuery); IObjectQuery_Next(pQuery))
1561 ObjID id = IObjectQuery_Object(pQuery);
1564 SafeRelease(pQuery);
1571 PlayerCbllmUpdate(ms
);
1572 BreathSimUpdateFrame(ms
);
1575 // post render frame updates
1576 void DPC_rend_update_frame(void)
1578 // update_player_medium_sounds();
1581 #pragma off(unreferenced)
1582 static bool key_handler_func(uiEvent
* ev
, Region
* r
, void* data
)
1584 uiCookedKeyEvent
* kev
= (uiCookedKeyEvent
*)ev
;
1585 return DPC_key_parse(kev
->code
);
1587 #pragma on(unreferenced)
1590 // In-game command terminal
1593 #define NUM_CMD_TERM_LINES 2
1594 #define NUM_BUG_TERM_LINES 10
1595 #define CMD_Y_MARGIN 2
1597 static void build_cmd_term(LGadRoot
* root
)
1599 Rect r
= *LGadBoxRect(root
);
1602 guiStyleSetupFont(NULL
,StyleFontNormal
);
1603 gr_string_size("X",&w
,&h
);
1604 guiStyleCleanupFont(NULL
,StyleFontNormal
);
1606 r
.lr
.y
= h
* NUM_CMD_TERM_LINES
+ CMD_Y_MARGIN
;
1607 CreateCommandTerminal(root
,&r
,kCmdTermHideUnfocused
);
1609 r
.lr
.y
= h
* NUM_BUG_TERM_LINES
+ CMD_Y_MARGIN
;
1610 CreateBugTerminal(root
,&r
,kCmdTermHideUnfocused
);
1613 static int key_handler_id
;
1614 static int mouse_handler_id
;
1616 void DPC_start_gamemode(void)
1618 LGadRoot
* root
= LGadCurrentRoot();
1619 uiInstallRegionHandler(LGadBoxRegion(root
),UI_EVENT_KBD_COOKED
,key_handler_func
,NULL
,&key_handler_id
);
1620 //uiInstallRegionHandler(LGadBoxRegion(root),UI_EVENT_MOUSE,mouse_handler_func,NULL,&mouse_handler_id);
1621 g_pInputBinder
->SetValidEvents (ALL_EVENTS
); // & (~UI_EVENT_MOUSE));
1627 //uiDoubleClickTime = 250;
1628 //uiDoubleClickDelay = 100;
1630 build_cmd_term(root
);
1632 if (gScrnLoopSetModeFailed
)
1634 cStr str
= FetchUIString("misc","set_mode_failed","strings");
1635 DPCOverlayAddText(str
,DEFAULT_MSG_TIME
);
1639 void DPC_end_gamemode(void)
1643 MouseMode(FALSE
,TRUE
);
1646 //uiDoubleClickTime = 0;
1647 //uiDoubleClickDelay = 0;
1651 if (DPC_mouse_loaded
)
1653 //DPC_mouse_hnd->Unlock();
1654 SafeFreeHnd(&DPC_mouse_hnd
);
1655 DPC_mouse_loaded
= FALSE
;
1658 LGadRoot
* root
= LGadCurrentRoot();
1659 uiRemoveRegionHandler(LGadBoxRegion(root
),key_handler_id
);
1660 AutoAppIPtr(PlayerGun
);
1662 DestroyCommandTerminal();
1663 DestroyBugTerminal();
1665 AutoAppIPtr(DPCCamera
);
1666 pDPCCamera
->SetEditMode(kCameraNormal
);
1671 void DPCSetViewRect(char* args)
1677 sscanf(args,"%d,%d,%d,%d",&x1,&y1,&x2,&y2);
1678 dpc_rend_rect.ul.x = x1;
1679 dpc_rend_rect.ul.y = y1;
1680 dpc_rend_rect.lr.x = x2;
1681 dpc_rend_rect.lr.y = y2;
1685 void SendSwitch(char *pObjName
)
1687 AutoAppIPtr(ScriptMan
);
1688 AutoAppIPtr(ObjectSystem
);
1690 ObjID objID
= pObjectSystem
->GetObjectNamed(pObjName
);
1691 if (objID
!= OBJ_NULL
)
1693 //mprintf("Sending fake TurnOn to obj %d (%s)\n",objID,pObjName);
1694 sScrMsg
msg(objID
, "TurnOn");
1695 pScriptMan
->SendMessage(&msg
);
1699 void TestHUD(int objID
)
1701 if (objID
!= OBJ_NULL
)
1703 gPropHUDTime
->Set(objID
, GetSimTime() + 5000);
1709 ////////////////////////////////////////////////////////////
1710 // PLAYER OBJECT CALLBACKS
1715 static void player_create_CB(ePlayerEvent event
, ObjID player
)
1722 // @TODO: get rid of this once the player archetype has the
1724 if (config_get_raw("player_model",buf
,sizeof(buf
)))
1726 buf
[sizeof(buf
)-1] = '\0';
1727 ObjSetModelName(player
,buf
);
1730 PhysCreateDefaultPlayer(player
);
1732 // make the player "special"
1733 cPhysModel
*pModel
= g_PhysModels
.Get(player
);
1734 Assert_(pModel
!= NULL
);
1735 pModel
->SetFlagState(kPMF_Special
, TRUE
);
1736 UpdatePhysProperty(player
, PHYS_TYPE
);
1738 AutoAppIPtr(NetManager
);
1739 if (pNetManager
->IsNetworkGame())
1741 // Register the player object in the proxy tables. This used
1742 // to happen at synch time, but now needs to be available
1743 // before we start processing the player's scripts.
1744 AutoAppIPtr(ObjectNetworking
);
1745 pObjectNetworking
->ObjRegisterProxy(player
, player
, player
);
1748 PlayerCbllmCreate(); // creates "lower brain" and body
1753 PlayerCbllmCreate(); // creates "lower brain" and body
1756 // @HACK: get the players connected to each other. This will
1757 // go away once we have the new joinup major mode.
1758 AutoAppIPtr(NetManager);
1759 if (pNetManager->IsNetworkGame()) {
1766 case kPlayerDestroy
:
1767 PlayerCbllmDestroy();
1773 // Look through the playerfactory links on the level. Ideally, we find
1774 // a link whose data is this player's playernum. If not, we use some other
1775 // link as a default.
1776 static ObjID
player_factory_CB(void)
1778 AutoAppIPtr_(LinkManager
,pLinkMan
);
1779 cAutoIPtr
<IRelation
> pRel ( pLinkMan
->GetRelationNamed("PlayerFactory") );
1782 AutoAppIPtr(NetManager
);
1783 if (pNetManager
->IsNetworkGame())
1785 myPlayerNum
= pNetManager
->MyPlayerNum();
1792 // LinkID id = pRel->GetSingleLink(LINKOBJ_WILDCARD,LINKOBJ_WILDCARD);
1793 LinkID defaultFactory
= LINKID_NULL
;
1794 LinkID id
= LINKID_NULL
;
1795 ILinkQuery
*pQuery
= pRel
->Query(LINKOBJ_WILDCARD
,LINKOBJ_WILDCARD
);
1799 // Run through the PlayerFactory links, and see if any of them work
1800 for ( ; (!pQuery
->Done()) && (id
== LINKID_NULL
); pQuery
->Next())
1802 int *factoryPtr
= (int *) pQuery
->Data();
1803 if (factoryPtr
== NULL
)
1805 // It's an old factory with no player num; use it as the
1807 defaultFactory
= pQuery
->ID();
1811 int factoryNum
= *factoryPtr
;
1812 if (factoryNum
== myPlayerNum
)
1814 // Got the right one
1817 else if (defaultFactory
== LINKID_NULL
)
1819 // We don't have any default yet, so try this one
1820 defaultFactory
= pQuery
->ID();
1825 SafeRelease(pQuery
);
1827 if (id
== LINKID_NULL
)
1829 // We didn't find an appropriate one, so fall back on a default
1830 if (defaultFactory
== LINKID_NULL
)
1832 // There aren't *any* factories on this level!
1837 id
= defaultFactory
;
1842 pRel
->Get(id
,&link
);
1846 static void setup_player_CB()
1848 HookPlayerCreate(player_create_CB
);
1849 HookPlayerFactory(player_factory_CB
);
1852 ////////////////////////////////////////////////////////////
1853 // CONTAINS LISTENER
1856 static BOOL
contain_CB(eContainsEvent ev
, ObjID outer
, ObjID inner
, eContainType
, ContainCBData
)
1860 case kContainRemove
:
1861 //ObjSetHasRefs(inner,TRUE);
1865 AutoAppIPtr(ObjectNetworking
);
1866 if (!pObjectNetworking
->ObjIsProxy(inner
))
1868 ObjSetHasRefs(inner
,FALSE
);
1869 // @HACK: Need to make sure this dereg gets broadcast, even
1870 // though the object's now in the container:
1871 PhysNetForceContainedMsgs(TRUE
);
1872 PhysDeregisterModel(inner
);
1873 PhysNetForceContainedMsgs(FALSE
);
1874 ObjForceReref(inner
);
1882 static void setup_contain_CB(void)
1884 AutoAppIPtr(ContainSys
);
1885 pContainSys
->Listen(OBJ_NULL
,contain_CB
,NULL
);
1888 ////////////////////////////////////////
1890 struct sCulpRelations
1896 static sCulpRelations culp_rels
[] =
1898 { "~Firer", kCulpTransitive
},
1902 #define NUM_CULP_RELS (sizeof(culp_rels)/sizeof(culp_rels[0]))
1904 // Set up culpability relations for dark
1905 static void DPC_init_culpability()
1907 // set up culpability listeners
1908 AutoAppIPtr_(LinkManager
,pLinkMan
);
1909 for (int i
= 0; i
< NUM_CULP_RELS
; i
++)
1911 sCulpRelations
& rel
= culp_rels
[i
];
1912 cAutoIPtr
<IRelation
> pRel
= pLinkMan
->GetRelationNamed(rel
.name
);
1913 AddCulpabilityRelation(pRel
,rel
.flags
);
1917 ///////////////////////////////////////////
1918 // Skill related parameters
1921 // Here's my descriptor, which identifies my stuff to the tag file & editor
1922 sFileVarDesc gBindTableDesc
=
1924 kCampaignVar
, // Where do I get saved?
1925 "BINDTABLE", // Tag file tag
1926 "Bind Table", // friendly name
1927 FILEVAR_TYPE(sBindTable
), // Type (for editing)
1929 {1, 0}, // last valid version
1930 "deepc", // optional: what game am I in NULL means all
1933 ////////////////////////////////////////
1934 extern void DPCOpenMFD(int which
);
1936 static void DPCSummonObj(char *args
)
1939 AutoAppIPtr(QuestData
);
1940 slim_mode
= pQuestData
->Get("HideInterface");
1942 // don't allow summoning (like nav markers) if we are pre-HUD
1946 AutoAppIPtr(ObjectSystem
);
1950 mxs_vector throwvec
= {1.0, 0, 0};
1952 arch
= pObjectSystem
->GetObjectNamed(args
);
1953 if (arch
== OBJ_NULL
)
1956 if (!OBJ_IS_CONCRETE(arch
))
1958 newobj
= pObjectSystem
->BeginCreate(arch
,kObjectConcrete
);
1959 pos
= ObjPosGet(PlayerObject());
1960 ObjPosSetLocation(newobj
, &pos
->loc
);
1961 pObjectSystem
->EndCreate(newobj
);
1962 //pGameTools->TeleportObject(newobj, pos->loc.vec, fac);
1963 PhysSetVelocity(newobj
, &throwvec
);
1967 static void DPCUbermensch(void)
1969 ObjID plr
= PlayerObject();
1970 if (plr
== OBJ_NULL
)
1973 // give the player max stats & skills
1976 for (i
=0; i
< 5; i
++)
1977 stats
.m_stats
[i
] = 6;
1978 g_BaseStatsProperty
->Set(plr
,&stats
);
1980 sWeaponSkills wpnskill
;
1981 for (i
=0; i
< 4; i
++)
1982 wpnskill
.m_wpn
[i
] = 6;
1983 g_BaseWeaponProperty
->Set(plr
,&wpnskill
);
1985 sTechSkills techskill
;
1986 for (i
=0; i
< 5; i
++)
1987 techskill
.m_tech
[i
] = 6;
1988 g_BaseTechProperty
->Set(plr
,&techskill
);
1990 AutoAppIPtr(DPCPlayer
);
1991 pDPCPlayer
->RecalcData(plr
);
1997 DPCOverlayAddText(AppName(),DEFAULT_MSG_TIME
);
2000 extern void DPCEditSynchBrushTextures(void);
2001 extern void DPCEditSynchBrushScales(void);
2002 extern void DPCEditSynchBrushFull(void);
2003 extern void DPCEditMakeDecalBrush(char *args
);
2004 //extern void DPCElevatorTest(char *args);
2005 extern void DPCLoadFull(const char *args
);
2006 extern void DPCGainPool(int amt
);
2007 extern void DPCTrainMFD(int amt
);
2008 extern void DPCLoadGameAndLevel(char *args
);
2010 static Command DPCDebugKeys
[] =
2013 //{ "elevator_test", FUNC_STRING, DPCElevatorTest, "Elevator-transport between two levels"},
2014 { "dpc_save_game", FUNC_INT
, DPCSaveGame
, ""},
2015 { "dpc_load_game", FUNC_INT
, TransModeLoadGame
, ""},
2017 { "dpc_load_full", FUNC_STRING
, DPCLoadFull
, ""},
2018 //{ "dpc_load_level", FUNC_STRING, DPCLoadGameAndLevel, "[dpc_load_level <slot> <name>] Loads the slot, and goes into the named level"},
2020 { "compute_fov", FUNC_VOID
, HackFOVCompute
, ""},
2021 { "letterbox", FUNC_BOOL
, DPCLetterboxSet
, "Set letterbox mode."},
2024 { "summon_obj", FUNC_STRING
, DPCSummonObj
, "Summon an object."},
2025 { "ubermensch", FUNC_VOID
, DPCUbermensch
, "Turns the player into homo superior."},
2026 { "add_pool", FUNC_INT
, DPCGainPool
, "Give player additional build pool points"},
2027 { "show_version", FUNC_VOID
, DPCVersion
, "Display version in game mode."},
2031 //{ "set_view_rect", FUNC_STRING, DPCSetViewRect, "Set the game view rect"},
2032 { "send_switch", FUNC_STRING
, SendSwitch
, "Send a switch message to an object"},
2033 { "test_HUD", FUNC_INT
, TestHUD
, "Put HUD brackets around an object."},
2035 { "camera_pos", FUNC_VOID
, CameraPositionSpew
, "spew the camera position"},
2036 { "camera_attach", FUNC_STRING
, DPCCameraAttach
, "attach the camera position"},
2037 { "camera_rec", FUNC_VOID
, SetCameraEditStateRecord
, "Set the camera edit state to record"},
2038 { "camera_edit", FUNC_VOID
, SetCameraEditStateEdit
, "Set the camera edit state to edit"},
2039 { "camera_play", FUNC_VOID
, SetCameraEditStatePlayback
, "Set the camera edit state to playback"},
2040 { "set_camera_speed", FUNC_FLOAT
, SetCameraEditSpeed
, "Set the edit camera speed"},
2041 { "make_scenes", FUNC_VOID
, MakeScenes
, "Make all the scene binaries"},
2042 { "cs_start", FUNC_INT
, CutSceneStart
, "Start a conversation-based cut-scene (conversationID)"},
2043 { "cs_rec", FUNC_INT
, CutSceneRecord
, "Record a new track for a conversation-based cut-scene (conversationID)"},
2044 { "cs_edit", FUNC_INT
, CutSceneEdit
, "Edit a conversation-based cut-scene (conversationID)"},
2045 { "cs_play", FUNC_INT
, CutScenePlayback
, "Playback a conversation-based cut-scene (conversationID)"},
2047 { "train_mfd", FUNC_INT
, DPCTrainMFD
, "Open up a training MFD"},
2049 { "synch_brush_tx", FUNC_VOID
, DPCEditSynchBrushTextures
, "Set all textures to current face val"},
2050 { "synch_brush_scale", FUNC_VOID
, DPCEditSynchBrushScales
, "Synch all txt scales to current faces val"},
2051 { "synch_brush_full", FUNC_VOID
, DPCEditSynchBrushFull
, "Synch textures & scales"},
2052 { "decal_brush", FUNC_STRING
, DPCEditMakeDecalBrush
, "[decal_brush x,y] Creates a decal brush off the selected face."},
2054 // { "update_creature_physics", FUNC_VOID, UpdateCreaturesPhysics, "Update special flag on creature physics"},
2059 extern void DrawHistoryToggle(void);
2060 extern void DPCPDAPlayUnreadLog();
2065 AutoAppIPtr(DPCPlayer
);
2066 AutoAppIPtr(ContainSys
);
2067 AutoAppIPtr(ScriptMan
);
2068 ObjID targetObj
, camObj
, player
= PlayerObject();
2069 BOOL hasCamera
= FALSE
;
2070 BOOL anySuccess
= FALSE
;
2073 sContainIter
*piter
= pContainSys
->IterStart(player
);
2075 while (!piter
->finished
)
2077 if (piter
->type
< DPCCONTAIN_PDOLLBASE
)
2079 if (gPropIsPlayerCamera
->IsRelevant(camObj
= piter
->containee
)) {
2084 pContainSys
->IterNext(piter
);
2087 pContainSys
->IterEnd(piter
);
2090 // TDB: play complaint
2094 if ((ammoCount
= GunStateGetAmmo(camObj
)) <= 0) {
2095 // TDB: play complaint
2099 sPropertyObjIter iter
;
2100 gPropIsCameraTarget
->IterStart(&iter
);
2101 while (gPropIsCameraTarget
->IterNext(&iter
,&targetObj
))
2103 // Camera targets have vhot 0 and vhot 1. vhot 0 is the point
2104 // to be photographed; vhot 1 is a little out from that in a
2105 // normal direction, so the angle of the photo can be enforced.
2106 BOOL success
= TRUE
;
2107 mxs_vector vHotLoc0
, vHotLoc1
, camPos
;
2108 Location loc0
, loc1
, hit
, camLoc
;
2109 ObjPos
*playPos
= ObjPosGet(player
);
2112 CameraGetLocation(PlayerCamera(), &camPos
, &camAng
);
2113 VHotGetLoc(&vHotLoc0
, targetObj
, 0);
2114 VHotGetLoc(&vHotLoc1
, targetObj
, 1);
2115 MakeLocationFromVector(&loc0
, &vHotLoc0
);
2116 MakeLocationFromVector(&loc1
, &vHotLoc1
);
2117 MakeLocationFromVector(&camLoc
, &camPos
);
2119 (!PhysRaycast(loc0
, camLoc
, &hit
, &hitObj
, 0.0) ==
2120 kCollideSphere
) && (hitObj
== player
)
2126 mxs_vector hot1Hot0Vec
;
2127 mx_sub_vec(&hot1Hot0Vec
, &vHotLoc1
, &vHotLoc0
);
2128 mxs_vector playerHot0Vec
;
2129 mx_sub_vec(&playerHot0Vec
, &camPos
, &vHotLoc0
);
2131 // Make sure not too far away
2132 #define MIN_CAMERA_TARGET_DIST 25
2133 if (mx_mag_vec(&playerHot0Vec
) > MIN_CAMERA_TARGET_DIST
) {
2137 // Make sure position is not too far off from normal (vhot0, vhot1)
2138 float dot
= mx_dot_vec(&hot1Hot0Vec
, &playerHot0Vec
);
2141 (mx_mag_vec(&hot1Hot0Vec
) * mx_mag_vec(&playerHot0Vec
)));
2142 #define MAX_CAMERA_TARGET_ANGLE 1.0 // 57 degrees
2143 if (fabs(angle
) > MAX_CAMERA_TARGET_ANGLE
) {
2147 // Make sure we are facing (near enough) the target by comparison
2149 // First figure out player facing direction
2150 mxs_matrix orientMat
;
2151 mx_ang2mat(&orientMat
, &camAng
);
2152 // Flip direction of of playerHot0Vec for some reason (so following
2153 // angle computation faces right way)
2154 mx_negeq_vec(&playerHot0Vec
);
2155 dot
= mx_dot_vec(&playerHot0Vec
, &orientMat
.vec
[0]);
2159 (mx_mag_vec(&playerHot0Vec
) * mx_mag_vec(&orientMat
.vec
[0])));
2161 #define MAX_SCREEN_ANGLE 0.6 // More than this and thing is probably off screen
2162 if (fabs(angle
) > MAX_SCREEN_ANGLE
) {
2167 // TBD: hook into quest
2169 sScrMsg
msg(player
,"PictureTaken");
2170 msg
.data
= targetObj
;
2171 pScriptMan
->SendMessage(&msg
);
2175 gPropIsCameraTarget
->IterStop(&iter
);
2177 sScrMsg
msg(player
,"UseCamera");
2178 msg
.data
= anySuccess
;
2179 pScriptMan
->SendMessage(&msg
);
2181 GunStateSetAmmo(camObj
, --ammoCount
);
2184 static Command DPCCommands
[] =
2186 // hotkey accelerators
2187 { "toggle_inv", FUNC_VOID
, DPCToggleInv
, "toggle inv panel"},
2188 { "cycle_ammo", FUNC_VOID
, DPCCycleAmmo
, "cycle through available ammo types"},
2189 { "toggle_compass", FUNC_VOID
, DPCToggleCompass
, "toggle compass state"},
2190 { "query", FUNC_INT
, DPCQueryMode
, "query cursor 1 = on 0 = off"},
2191 { "split", FUNC_INT
, DPCSplitMode
, "split cursor 1 = on 0 = off"},
2192 { "DPC_jump_player", FUNC_VOID
, DPCPlayerJump
, "jump the player"},
2193 { "look_cursor", FUNC_VOID
, DPCLookCursor
, "puts cursor into look mode"},
2194 { "reload_gun", FUNC_VOID
, DPCAmmoReload
, "reloads weapon out of inventory"},
2195 { "swap_guns", FUNC_VOID
, DPCSwapGuns
, "switches primary and secondary weapons"},
2196 { "wpn_setting_toggle", FUNC_VOID
, DPCSettingToggle
, "toggles between weapon settings"},
2197 { "equip_weapon", FUNC_STRING
, DPCWeaponEquip
, "searches your inv for a particular weapon and equips it"},
2198 { "cycle_weapon", FUNC_INT
, DPCWeaponCycle
, "Cycles through next equippable weapon, 1 for fwd, -1 for back"},
2199 { "clear_weapon", FUNC_VOID
, DPCWeaponUnequip
, "unequips current weapon"},
2200 { "unjam_weapon", FUNC_VOID
, DPCWeaponUnjam
, "Attempts to unjam current weapon"},
2201 { "open_mfd", FUNC_INT
, DPCOpenMFD
, "Open up an MFD by overlay constant"},
2202 { "stop_email", FUNC_VOID
, DPCEmailStop
, "Stop any currently playing email/log"},
2203 { "use_obj", FUNC_STRING
, DPCUseObj
, "Use an object by name"},
2204 { "msg_history", FUNC_VOID
, DrawHistoryToggle
, "Toggle message history"},
2205 { "play_unread_log", FUNC_VOID
, DPCPDAPlayUnreadLog
, "Play an unread log"},
2206 { "use_camera", FUNC_VOID
, DPCUseCamera
, "Use camera"},
2208 // basic interface support
2209 { "toggle_mouse", FUNC_VOID
, DPCToggleMode
, "switch between mouselook & cursor modes"},
2210 { "frob_toggle", FUNC_VOID
, DPCFrobAndMaybeToggleMode
, "switch between modes, also frobbing current selection"},
2211 { "frob_object", FUNC_VOID
, DPCFrobObject
, "simple frob of selected object"},
2212 { "frob_object_inv", FUNC_VOID
, DPCFrobObjectInv
, "simple frob of selected object, in world or in inv"},
2213 { "mp_hilight_obj", FUNC_VOID
, DPCHilightObject
, "hilight an object in MP game"},
2214 //{ "interface_click", FUNC_VOID, DPCInterfaceClick, "interact with objects / interface" },
2215 { "interface_use", FUNC_VOID
, DPCInterfaceUseItem
, "inv use an item"},
2216 { "fire_weapon", FUNC_INT
, DPCFireWeapon
, "fire weapon 1 = start 0 = finish"},
2217 { "drag_and_drop", FUNC_INT
, DPCDragDropSimple
, "drag & drop 1 = start 0 = finish"},
2218 { "drag_and_drop_frob", FUNC_INT
, DPCDragDropFrob
, "drag & drop 1 = start 0 = finish"},
2219 { "drag_and_drop_mode", FUNC_INT
, DPCDragDropMode
, "drag & drop 1 = start 0 = finish"},
2220 //{ "dragndrop", FUNC_VOID, DPCBeginDragDrop, "begin drag & drop operation" },
2221 //{ "end_dragndrop", FUNC_VOID, DPCBeginDragDrop, "begin drag & drop operation" },
2223 //{ "fire_at_cursor", FUNC_INT, DPCFireCursor, "fire weapon at cursor, 1=start 0=finish"},
2224 { "test_begin", FUNC_VOID
, DPCBeginGame
, ""},
2225 { "quicksave", FUNC_VOID
, DPCQuickSaveHack
, "Save to 'current' subdir."},
2226 { "quickload", FUNC_VOID
, DPCQuickLoad
, "Load from 'current' subdir."},
2229 // Init the Deep Cover-specific game tools.
2230 void DPCToolsInit(void)
2232 IGameTools
* pGameTools
= AppGetObj(IGameTools
);
2233 pGameTools
->SetIsToGameModeGUIDCallback(DPCIsToGameModeGUID
);
2234 SafeRelease(pGameTools
);
2237 void DPC_init_game(void)
2239 COMMANDS(DPCCommands
,HK_ALL
); // GAME_MODE | HK_GAME2_MODE);
2240 // note, debug keys are included in ship build as cheat keys
2241 COMMANDS(DPCDebugKeys
,HK_ALL
);
2243 // Install damage listener/filters
2244 IDamageModel
* pDamageModel
= AppGetObj(IDamageModel
);
2245 pDamageModel
->Listen(kDamageMsgImpact
| kDamageMsgSlay
| kDamageMsgDamage
, DPCDamageListener
, NULL
);
2246 pDamageModel
->Listen(kDamageMsgTerminate
, DPCLootDamageListener
,NULL
);
2247 SafeRelease(pDamageModel
);
2257 // man, we should clean this up some
2258 AutoAppIPtr(PlayerGun
);
2259 pPlayerGun
->GameInit();
2260 DPCPropertiesInit();
2261 CannisterPropertyInit();
2262 InvDimsPropertyInit();
2263 DoorOpenSoundPropertyInit();
2264 DoorCloseSoundPropertyInit();
2265 DoorTimerPropertyInit();
2267 ObjSoundNamePropInit();
2271 DPCFrobPropertiesInit();
2272 DPCPlayerDamageInit();
2275 MeleeTypePropertyInit();
2277 DarkDifficultyInit();
2280 CameraObjPropertyInit();
2282 GunProjectileInit();
2288 DPCOverlayListenInit();
2290 SetGameIBVarsFunc (InitDPCIBVars
);
2292 DPCOptionsMenuInit();
2293 DPCMasterModeInit();
2296 DPC_init_culpability();
2299 // Network messages for the game level:
2300 g_pThrowObjMsg
= new cNetMsg(&sThrowObjDesc
);
2307 BOOL start_game
= config_is_defined("play");
2309 BOOL start_game
= TRUE
;
2312 // hack to set initial difficulty level
2314 config_get_int("difficulty",&diffval
);
2315 AutoAppIPtr(QuestData
);
2316 pQuestData
->Create("Difficulty",diffval
,kQuestDataCampaign
);
2320 gPrimordialMode
= DescribeDPCMasterMode();
2322 if (config_is_defined("quick_start"))
2324 gPrimordialMode
= DescribeDPCInitGameMode();
2328 void DPC_term_game(void)
2330 DPCDamageShutDown();
2332 DPCPlayerDamageTerm();
2333 AutoAppIPtr(PlayerGun
);
2334 pPlayerGun
->GameTerm();
2336 DPCPropertiesShutdown();
2337 MeleeTypePropertyShutdown();
2339 DarkDifficultyTerm();
2342 CameraObjPropertyTerm();
2343 DPCOptionsMenuTerm();
2346 DPCMasterModeTerm();
2347 GunProjectileTerm();
2354 // Delete network message:
2355 delete g_pThrowObjMsg
;