2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 ///////////////////////////////////////////////////////////////////////////////
7 // $Header: r:/t2repos/thief2/src/sim/doorprop.cpp,v 1.23 2000/03/07 19:54:00 toml Exp $
37 // Must be last header
40 ////////////////////////////////////////////////////////////////////////////////
42 IRotDoorProperty
*g_pRotDoorProperty
;
43 ITransDoorProperty
*g_pTransDoorProperty
;
45 ////////////////////////////////////////////////////////////////////////////////
47 sDoorProp
*GetDoorProperty(int o_id
)
49 sRotDoorProp
*pRotDoorProp
;
50 sTransDoorProp
*pTransDoorProp
;
52 if (g_pRotDoorProperty
->Get(o_id
, &pRotDoorProp
))
53 return (sDoorProp
*)pRotDoorProp
;
55 if (g_pTransDoorProperty
->Get(o_id
, &pTransDoorProp
))
56 return (sDoorProp
*)pTransDoorProp
;
61 ////////////////////////////////////////////////////////////////////////////////
64 static sPropertyConstraint door_constraints
[] =
66 { kPropertyRequires
, PHYS_TYPE_NAME
},
67 { kPropertyNullConstraint
}
70 ////////////////////////////////////////////////////////////////////////////////
76 static sPropertyDesc RotPropDesc
=
79 kPropertyNoInherit
| kPropertyInstantiate
,
82 0, // last ok version (0 means no other ok versions)
83 { "Door", "Rotating" },
84 kPropertyChangeLocally
,
88 // Hey kids, lets get our own notify
90 typedef cGenericProperty
<IRotDoorProperty
,&IID_IRotDoorProperty
, sRotDoorProp
*> cRotDoorPropertyBase
;
92 class cRotDoorProperty
: public cRotDoorPropertyBase
94 cClassDataOps
< sRotDoorProp
> mOps
;
97 cRotDoorProperty(const sPropertyDesc
* desc
, IPropertyStore
* store
)
98 : cRotDoorPropertyBase(desc
,store
)
103 cRotDoorProperty(const sPropertyDesc
* desc
, ePropertyImpl impl
)
104 : cRotDoorPropertyBase(desc
,NULL
)
106 IPropertyStore
* store
= CreateGenericPropertyStore(impl
);
111 STDMETHOD_(void,Notify
)(ePropertyNotifyMsg msg
, PropNotifyData data
)
113 switch(NOTIFY_MSG(msg
))
115 case kObjNotifyPostLoad
:
116 GenerateAllDoorRooms();
119 cRotDoorPropertyBase::Notify(msg
,data
);
122 STANDARD_DESCRIBE_TYPE( sRotDoorProp
);
125 ////////////////////////////////////////
127 static const char *pDoorStates
[5] =
136 static const char *pDoorAxes
[3] =
143 static sFieldDesc RotDoorPropFields
[] =
145 { "Closed Angle", kFieldTypeFloat
, FieldLocation(sRotDoorProp
, closed
), kFieldFlagNone
},
146 { "Open Angle", kFieldTypeFloat
, FieldLocation(sRotDoorProp
, open
), kFieldFlagNone
},
147 { "Base Speed", kFieldTypeFloat
, FieldLocation(sRotDoorProp
, base_speed
), kFieldFlagNone
},
148 { "Axis", kFieldTypeEnum
, FieldLocation(sRotDoorProp
, axis
), kFieldFlagNone
, 0, 3, 3, pDoorAxes
},
149 { "Status", kFieldTypeEnum
, FieldLocation(sRotDoorProp
, status
), kFieldFlagNone
, 0, 5, 5, pDoorStates
},
150 { "Hard Limits?", kFieldTypeBool
, FieldLocation(sRotDoorProp
, hard_limits
), kFieldFlagNone
},
151 { "Blocks Vision?", kFieldTypeBool
, FieldLocation(sRotDoorProp
, vision_blocking
), kFieldFlagNone
},
152 { "Blocks Sound %", kFieldTypeFloat
, FieldLocation(sRotDoorProp
, sound_blocking
), kFieldFlagNone
},
153 { "Push Mass", kFieldTypeFloat
, FieldLocation(sRotDoorProp
, push_mass
), kFieldFlagNone
},
154 { "Clockwise?", kFieldTypeBool
, FieldLocation(sRotDoorProp
, clockwise
), kFieldFlagNone
},
155 { "Room ID #1", kFieldTypeInt
, FieldLocation(sRotDoorProp
, room1
), kFieldFlagNotEdit
},
156 { "Room ID #2", kFieldTypeInt
, FieldLocation(sRotDoorProp
, room2
), kFieldFlagNotEdit
},
160 static sStructDesc RotDoorDesc
= StructDescBuild(sRotDoorProp
, kStructFlagNone
, RotDoorPropFields
);
162 ////////////////////////////////////////
164 void LGAPI
RotDoorListener(sPropertyListenMsg
*msg
, PropListenerData data
);
165 static void SetupRotDoorProperty(void);
167 ////////////////////////////////////////
169 class cRotDoorOps
: public cClassDataOps
<sRotDoorProp
>
172 STDMETHOD_(int,Version
)();
173 STDMETHOD(Read
)(sDatum
* dat
, IDataOpsFile
* file
, int version
);
176 typedef cHashPropertyStore
<cRotDoorOps
> cRotDoorStore
;
178 typedef cSpecificProperty
<IRotDoorProperty
, &IID_IRotDoorProperty
, sRotDoorProp
*, cRotDoorStore
> cBaseRotDoorProp
;
180 class cRotDoorProp
: public cBaseRotDoorProp
183 cRotDoorProp(const sPropertyDesc
* desc
) : cBaseRotDoorProp(desc
) {};
185 STANDARD_DESCRIBE_TYPE(sRotDoorProp
);
188 STDMETHODIMP_(int) cRotDoorOps::Version()
193 STDMETHODIMP
cRotDoorOps::Read(sDatum
* pdat
, IDataOpsFile
* file
, int v
)
198 sRotDoorProp
*pRotDoorProp
= (sRotDoorProp
*)pdat
->value
;
200 file
->Read(&pRotDoorProp
->type
, sizeof(int));
201 file
->Read(&pRotDoorProp
->closed
, sizeof(mxs_real
));
202 file
->Read(&pRotDoorProp
->open
, sizeof(mxs_real
));
203 file
->Read(&pRotDoorProp
->base_speed
, sizeof(mxs_real
));
204 file
->Read(&pRotDoorProp
->axis
, sizeof(int));
205 file
->Read(&pRotDoorProp
->status
, sizeof(int));
206 file
->Read(&pRotDoorProp
->hard_limits
, sizeof(BOOL
));
207 file
->Read(&pRotDoorProp
->sound_blocking
, sizeof(mxs_real
));
208 file
->Read(&pRotDoorProp
->vision_blocking
, sizeof(BOOL
));
210 pRotDoorProp
->push_mass
= 25.0;
212 file
->Read(&pRotDoorProp
->push_mass
, sizeof(mxs_real
));
213 file
->Read(&pRotDoorProp
->base_closed_location
, sizeof(mxs_vector
));
214 file
->Read(&pRotDoorProp
->base_open_location
, sizeof(mxs_vector
));
215 file
->Read(&pRotDoorProp
->base_location
, sizeof(mxs_vector
));
216 file
->Read(&pRotDoorProp
->base_angle
, sizeof(mxs_angvec
));
217 file
->Read(&pRotDoorProp
->base
, sizeof(mxs_real
));
218 file
->Read(&pRotDoorProp
->room1
, sizeof(int));
219 file
->Read(&pRotDoorProp
->room2
, sizeof(int));
220 file
->Read(&pRotDoorProp
->clockwise
, sizeof(BOOL
));
223 file
->Read(&pRotDoorProp
->base_closed_facing
, sizeof(mxs_angvec
));
224 file
->Read(&pRotDoorProp
->base_open_facing
, sizeof(mxs_angvec
));
230 ////////////////////////////////////////
232 IRotDoorProperty
*RotDoorPropertyInit(void)
234 SetupRotDoorProperty();
236 g_pRotDoorProperty
= new cRotDoorProp(&RotPropDesc
);
239 g_pRotDoorProperty
->Listen(kListenPropModify
| kListenPropSet
| kListenPropUnset
| kListenPropLoad
,
240 RotDoorListener
, NULL
);
242 return g_pRotDoorProperty
;
245 ////////////////////////////////////////
247 void RotDoorPropertyTerm(void)
249 SafeRelease(g_pRotDoorProperty
);
252 ////////////////////////////////////////
254 static void SetupRotDoorProperty(void)
256 StructDescRegister(&RotDoorDesc
);
259 ////////////////////////////////////////
261 BOOL rot_door_lock
= FALSE
;
263 void LGAPI
RotDoorListener(sPropertyListenMsg
*msg
, PropListenerData data
)
265 sRotDoorProp
*pDoorProp
;
267 if (!msg
->value
.ptrval
|| rot_door_lock
)
270 pDoorProp
= (sRotDoorProp
*)msg
->value
.ptrval
;
273 if (OBJ_IS_CONCRETE(msg
->obj
) && !PhysObjHasPhysics(msg
->obj
) && !(msg
->type
& kListenPropUnset
))
274 PhysRegisterOBBDefault(msg
->obj
);
278 if ((msg
->type
& kListenPropLoad
) && (pDoorProp
->status
!= kDoorClosed
))
282 if ((pModel
= g_PhysModels
.Get(msg
->obj
)) != NULL
)
284 pModel
->ClearAngleLimits();
286 mxs_angvec cur_ang
= ObjPosGet(msg
->obj
)->fac
;
287 ObjRotate(msg
->obj
, &pDoorProp
->base_angle
);
289 pModel
->AddAngleLimit(pDoorProp
->axis
, pDoorProp
->open
, RotDoorOpenCallback
);
290 pModel
->AddAngleLimit(pDoorProp
->axis
, 0, RotDoorCloseCallback
);
292 ObjRotate(msg
->obj
, &cur_ang
);
300 if (msg
->type
& kListenPropSet
)
302 if (!(msg
->type
& kListenPropModify
))
304 // default to the z-axis and 1.0 radians/sec
306 pDoorProp
->base_speed
= 1.0;
308 pDoorProp
->type
= ROTATING_DOOR
;
310 pDoorProp
->vision_blocking
= TRUE
;
311 pDoorProp
->sound_blocking
= 60.0;
313 pDoorProp
->push_mass
= 25.0;
315 pDoorProp
->room1
= -1;
316 pDoorProp
->room2
= -1;
319 if (OBJ_IS_CONCRETE(msg
->obj
))
321 UpdateDoorPhysics(msg
->obj
);
322 UpdateDoorBrush(msg
->obj
);
326 g_pRotDoorProperty
->Set(msg
->obj
, pDoorProp
);
333 if (msg
->type
& kListenPropModify
)
335 // check for valid axis
336 if ((pDoorProp
->axis
< 0) || (pDoorProp
->axis
> 2))
339 // check for valid status
340 if ((pDoorProp
->status
< 0) || (pDoorProp
->status
> 3))
341 pDoorProp
->status
= 0;
343 // check for valid angle
344 if (pDoorProp
->open
< 0)
346 while (pDoorProp
->open
< 0)
347 pDoorProp
->open
+= 360.0;
348 while (pDoorProp
->open
>= 360)
349 pDoorProp
->open
-= 360.0;
351 if (pDoorProp
->closed
< 0)
353 while (pDoorProp
->closed
< 0)
354 pDoorProp
->closed
+= 360.0;
355 while (pDoorProp
->closed
>= 360)
356 pDoorProp
->closed
-= 360.0;
359 if (OBJ_IS_CONCRETE(msg
->obj
))
361 UpdateDoorPhysics(msg
->obj
);
362 GenerateBaseDoorLocations(msg
->obj
);
366 g_pRotDoorProperty
->Set(msg
->obj
, pDoorProp
);
373 if (msg
->type
& kListenPropUnset
)
379 ////////////////////////////////////////////////////////////////////////////////
385 static sPropertyDesc TransPropDesc
=
388 kPropertyNoInherit
| kPropertyInstantiate
,
391 0, // last ok version (0 means no other ok versions)
392 { "Door", "Translating" },
393 kPropertyChangeLocally
,
396 typedef cGenericProperty
<ITransDoorProperty
,&IID_ITransDoorProperty
, sTransDoorProp
*> cTransDoorPropertyBase
;
398 class cTransDoorProperty
: public cTransDoorPropertyBase
400 cClassDataOps
< sTransDoorProp
> mOps
;
403 cTransDoorProperty(const sPropertyDesc
* desc
, IPropertyStore
* store
)
404 : cTransDoorPropertyBase(desc
,store
)
409 cTransDoorProperty(const sPropertyDesc
* desc
, ePropertyImpl impl
)
410 : cTransDoorPropertyBase(desc
,CreateGenericPropertyStore(impl
))
415 STANDARD_DESCRIBE_TYPE( sTransDoorProp
);
418 ////////////////////////////////////////
420 static sFieldDesc TransDoorPropFields
[] =
422 { "Closed Position", kFieldTypeFloat
, FieldLocation(sTransDoorProp
, closed
), kFieldFlagNone
},
423 { "Open Position", kFieldTypeFloat
, FieldLocation(sTransDoorProp
, open
), kFieldFlagNone
},
424 { "Base Speed", kFieldTypeFloat
, FieldLocation(sTransDoorProp
, base_speed
), kFieldFlagNone
},
425 { "Axis", kFieldTypeEnum
, FieldLocation(sTransDoorProp
, axis
), kFieldFlagNone
, 0, 3, 3, pDoorAxes
},
426 { "Status", kFieldTypeEnum
, FieldLocation(sTransDoorProp
, status
), kFieldFlagNone
, 0, 5, 5, pDoorStates
},
427 { "Hard Limits?", kFieldTypeBool
, FieldLocation(sTransDoorProp
, hard_limits
), kFieldFlagNone
},
428 { "Blocks Vision?", kFieldTypeBool
, FieldLocation(sRotDoorProp
, vision_blocking
), kFieldFlagNone
},
429 { "Blocks Sound %", kFieldTypeFloat
, FieldLocation(sRotDoorProp
, sound_blocking
), kFieldFlagNone
},
430 { "Push Mass", kFieldTypeFloat
, FieldLocation(sRotDoorProp
, push_mass
), kFieldFlagNone
},
431 { "Room ID #1", kFieldTypeInt
, FieldLocation(sRotDoorProp
, room1
), kFieldFlagNotEdit
},
432 { "Room ID #2", kFieldTypeInt
, FieldLocation(sRotDoorProp
, room2
), kFieldFlagNotEdit
},
436 static sStructDesc TransDoorDesc
= StructDescBuild(sTransDoorProp
, kStructFlagNone
, TransDoorPropFields
);
438 ////////////////////////////////////////
440 void LGAPI
TransDoorListener(sPropertyListenMsg
*msg
, PropListenerData data
);
441 static void SetupTransDoorProperty(void);
443 ////////////////////////////////////////
445 class cTransDoorOps
: public cClassDataOps
<sTransDoorProp
>
448 STDMETHOD_(int,Version
)();
449 STDMETHOD(Read
)(sDatum
* dat
, IDataOpsFile
* file
, int version
);
452 typedef cHashPropertyStore
<cTransDoorOps
> cTransDoorStore
;
454 typedef cSpecificProperty
<ITransDoorProperty
, &IID_ITransDoorProperty
, sTransDoorProp
*, cTransDoorStore
> cBaseTransDoorProp
;
456 class cTransDoorProp
: public cBaseTransDoorProp
459 cTransDoorProp(const sPropertyDesc
* desc
) : cBaseTransDoorProp(desc
) {};
461 STANDARD_DESCRIBE_TYPE(sTransDoorProp
);
464 STDMETHODIMP_(int) cTransDoorOps::Version()
469 STDMETHODIMP
cTransDoorOps::Read(sDatum
* pdat
, IDataOpsFile
* file
, int v
)
474 sTransDoorProp
*pTransDoorProp
= (sTransDoorProp
*)pdat
->value
;
476 file
->Read(&pTransDoorProp
->type
, sizeof(int));
477 file
->Read(&pTransDoorProp
->closed
, sizeof(mxs_real
));
478 file
->Read(&pTransDoorProp
->open
, sizeof(mxs_real
));
479 file
->Read(&pTransDoorProp
->base_speed
, sizeof(mxs_real
));
480 file
->Read(&pTransDoorProp
->axis
, sizeof(int));
481 file
->Read(&pTransDoorProp
->status
, sizeof(int));
482 file
->Read(&pTransDoorProp
->hard_limits
, sizeof(BOOL
));
483 file
->Read(&pTransDoorProp
->sound_blocking
, sizeof(mxs_real
));
484 file
->Read(&pTransDoorProp
->vision_blocking
, sizeof(BOOL
));
486 pTransDoorProp
->push_mass
= 25.0;
488 file
->Read(&pTransDoorProp
->push_mass
, sizeof(mxs_real
));
489 file
->Read(&pTransDoorProp
->base_closed_location
, sizeof(mxs_vector
));
490 file
->Read(&pTransDoorProp
->base_open_location
, sizeof(mxs_vector
));
491 file
->Read(&pTransDoorProp
->base_location
, sizeof(mxs_vector
));
492 file
->Read(&pTransDoorProp
->base_angle
, sizeof(mxs_angvec
));
493 file
->Read(&pTransDoorProp
->base
, sizeof(mxs_real
));
494 file
->Read(&pTransDoorProp
->room1
, sizeof(int));
495 file
->Read(&pTransDoorProp
->room2
, sizeof(int));
500 ////////////////////////////////////////
502 ITransDoorProperty
*TransDoorPropertyInit(void)
504 SetupTransDoorProperty();
505 g_pTransDoorProperty
= new cTransDoorProp(&TransPropDesc
);
508 g_pTransDoorProperty
->Listen(kListenPropModify
| kListenPropSet
| kListenPropUnset
| kListenPropLoad
,
509 TransDoorListener
, NULL
);
511 return g_pTransDoorProperty
;
514 ////////////////////////////////////////
516 void TransDoorPropertyTerm(void)
518 SafeRelease(g_pTransDoorProperty
);
521 ////////////////////////////////////////
523 static void SetupTransDoorProperty(void)
525 StructDescRegister(&TransDoorDesc
);
528 ////////////////////////////////////////
530 static BOOL trans_door_lock
= FALSE
;
532 #define TRANS_DOOR_LOCK trans_door_lock = TRUE
533 #define TRANS_DOOR_UNLOCK trans_door_lock = FALSE
535 void LGAPI
TransDoorListener(sPropertyListenMsg
*msg
, PropListenerData data
)
537 sTransDoorProp
*pDoorProp
;
539 if (!msg
->value
.ptrval
|| trans_door_lock
)
542 pDoorProp
= (sTransDoorProp
*)msg
->value
.ptrval
;
544 if (OBJ_IS_CONCRETE(msg
->obj
) && !PhysObjHasPhysics(msg
->obj
) && !(msg
->type
& kListenPropUnset
))
545 PhysRegisterOBBDefault(msg
->obj
);
548 if ((msg
->type
& kListenPropLoad
) && (pDoorProp
->status
!= kDoorClosed
))
552 if ((pModel
= g_PhysModels
.Get(msg
->obj
)) != NULL
)
554 pModel
->ClearTransLimits();
555 pModel
->AddTransLimit(pDoorProp
->base_open_location
, TransDoorOpenCallback
);
556 pModel
->AddTransLimit(pDoorProp
->base_closed_location
, TransDoorClosedCallback
);
563 if (msg
->type
& kListenPropSet
)
565 if (!(msg
->type
& kListenPropModify
))
567 // default to the x-axis and 1.0 ft/sec
569 pDoorProp
->base_speed
= 1.0;
571 pDoorProp
->type
= TRANSLATING_DOOR
;
573 pDoorProp
->vision_blocking
= TRUE
;
574 pDoorProp
->sound_blocking
= 60.0;
576 pDoorProp
->push_mass
= 25.0;
578 pDoorProp
->room1
= -1;
579 pDoorProp
->room2
= -1;
582 if (OBJ_IS_CONCRETE(msg
->obj
))
584 UpdateDoorPhysics(msg
->obj
);
585 UpdateDoorBrush(msg
->obj
);
589 g_pTransDoorProperty
->Set(msg
->obj
, pDoorProp
);
596 if (msg
->type
& kListenPropModify
)
598 // check for valid axis
599 if ((pDoorProp
->axis
< 0) || (pDoorProp
->axis
> 2))
604 g_pTransDoorProperty
->Set(msg
->obj
, pDoorProp
);
608 // check for valid status
609 if ((pDoorProp
->status
< 0) || (pDoorProp
->status
> 3))
611 pDoorProp
->status
= 0;
614 g_pTransDoorProperty
->Set(msg
->obj
, pDoorProp
);
618 if (OBJ_IS_CONCRETE(msg
->obj
))
620 GenerateBaseDoorLocations(msg
->obj
);
621 UpdateDoorPhysics(msg
->obj
);
628 if (msg
->type
& kListenPropUnset
)