2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
27 #define AIUsesDoors(obj) AIGetProperty(g_pAIUsesDoorsProperty, (obj), TRUE)
29 static IBoolProperty
* g_pAIUsesDoorsProperty
= NULL
;
30 static IRelation
* g_pSwitchLinkRelation
= NULL
;
32 ///////////////////////////////////////
34 void DPCAITermPathfinder(void)
36 SafeRelease(g_pAIUsesDoorsProperty
);
39 ///////////////////////////////////////
41 STDMETHODIMP_(const char *) cDPCAIPathfinder::GetName()
43 return "DPC pathfinding component";
46 ////////////////////////////////////////
51 inline BOOL
DPCAIIsTripwire(ObjID objID
)
53 return gPropTripFlags
->IsRelevant(objID
);
56 ////////////////////////////////////////
58 // Is this object a quest filter that should currently be "locking" this door?
59 // This is really a hack, but we assume that anything with the QB Name property on
60 // it is a QuestFilter.
63 BOOL
cDPCAIPathfinder::QuestBlock(ObjID objID
) const
69 // Start by checking for quest props on obj
70 if (!gPropQBName
->Get(objID
, &pQBName
))
72 gPropQBVal
->Get(objID
, &QBVal
);
73 AutoAppIPtr(QuestData
);
74 val
= pQuestData
->Get(pQBName
);
81 ///////////////////////////////////////
83 // Recursive search back along switch links to specified depth.
84 // This function returns the result in the openable parameter.
85 // It is defensive in the sense that it will return FALSE if any lock
86 // or unset quest bit is encountered in the search. It will only return
87 // true if it encounters a tripwire and no locks or unset quest bits.
88 // The actual function return value is used to specify whether to continue
90 // The initial value of the openable parameter is assumed to be FALSE.
93 BOOL
cDPCAIPathfinder::DoorOpenable(ObjID objID
, int depth
, BOOL
& openable
)
95 cAutoLinkQuery
query(g_pSwitchLinkRelation
, LINKOBJ_WILDCARD
, objID
);
100 while (!query
->Done())
102 ObjID sourceID
= query
.GetSource();
105 // Check for impassable.
106 // Assume that anything with a keypad code property on it is a keypad
107 if (ObjSelfLocked(sourceID
) || QuestBlock(sourceID
) || g_pPropKeypadCode
->Get(sourceID
, &keypadCode
))
112 if (DPCAIIsTripwire(sourceID
))
114 if ((depth
>1) && !DoorOpenable(sourceID
, depth
-1, openable
))
121 ///////////////////////////////////////
123 STDMETHODIMP_(BOOL
) cDPCAIPathfinder::CanPassDoor(ObjID door
)
127 // This is kind of stupid, but avoids ordering issues with init functions (& the AI)
128 if (g_pAIUsesDoorsProperty
== NULL
)
130 AutoAppIPtr(PropertyManager
);
131 g_pAIUsesDoorsProperty
= (IBoolProperty
*)pPropertyManager
->GetPropertyNamed("AI_UsesDoors");
132 Assert_(g_pAIUsesDoorsProperty
);
134 if (g_pSwitchLinkRelation
== NULL
)
136 AutoAppIPtr(LinkManager
);
137 g_pSwitchLinkRelation
= pLinkManager
->GetRelationNamed("SwitchLink");
138 Assert_(g_pSwitchLinkRelation
);
141 if (!AIUsesDoors(GetID()))
144 if (!IsDoor(door
) || GetDoorStatus(door
) == kDoorOpen
|| GetDoorStatus(door
) == kDoorOpening
)
147 // just do 2 deep search for now
149 DoorOpenable(door
, 2, openable
);
151 // The idea is that any unlocked, non-questy, closed door should be openable.
152 // In Shock, everything had to be hooked to a tripwire (tripped by either the AI or the player).
153 // This is no longer the case in DeepC. I'm leaving in support for Shock-style while allowing the Thief-style.
155 (GetDoorStatus(door
) == kDoorClosed
) &&
156 (!ObjSelfLocked(door
)) &&