2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // $Header: r:/t2repos/thief2/src/shock/shkpatch.cpp,v 1.10 2000/02/19 13:25:51 toml Exp $
7 // code for doing patch like things to the levels
28 #include <dbmem.h> // must be last header!
30 // Objnum conversion. Deals with objnum remapping, as well as making sure
31 // that this really is the right object. May return OBJ_NULL if we can't
32 // safely resolve the objnum.
33 static ObjID
RealObj(ObjID old_obj
, const char *arch_name
)
35 AutoAppIPtr(ObjectSystem
);
36 AutoAppIPtr(TraitManager
);
37 ObjID obj
= pObjectSystem
->RemapOnLoad(old_obj
);
38 ObjID archetype
= pObjectSystem
->GetObjectNamed(arch_name
);
39 if (pTraitManager
->GetArchetype(obj
) != archetype
)
47 // Make an object local-only
48 static void MakeLocal(ObjID old_obj
, const char *archetype
)
50 AutoAppIPtr(ObjectSystem
);
51 ObjID obj
= RealObj(old_obj
, archetype
);
53 SetNetworkCategory(obj
, kLocalOnly
);
56 // Mark an object as moving terrain
57 static void MakeMovingTerrain(ObjID startObj
, const char *pArchetype
)
59 ObjID obj
= RealObj(startObj
, pArchetype
);
62 cMovingTerrainProp pMTProp
;
63 pMTProp
.active
= FALSE
;
64 pMTProp
.prev_state
= FALSE
;
65 g_pMovingTerrainProperty
->Set(obj
, &pMTProp
);
69 // Macro to test whether an update is needed. Intended to be used inside
71 #define NEED_UPDATE(target, patchlevel) \
72 ((stricmp(level, target) == 0) &&\
73 (old_ver < patchlevel) &&\
74 (new_ver >= patchlevel))
76 void PatchLevelData(char *level
, int old_ver
, int new_ver
)
79 if (config_is_defined("loud_level_patch"))
80 mprintf("Want to patch %s from %d to %d\n",level
,old_ver
,new_ver
);
83 AutoAppIPtr(ObjectSystem
);
85 if (NEED_UPDATE("ops3.mis", 1))
87 // Make the glue elements of the massacre cutscene local-only
88 MakeLocal(136, "Sound Trap");
89 MakeLocal(1066, "Simple Button");
90 MakeLocal(1067, "Sound Trap");
91 MakeLocal(1068, "Trigger Delay");
92 MakeLocal(1069, "Sound Trap");
93 MakeLocal(1070, "Trigger Delay");
94 MakeLocal(1071, "Sound Trap");
95 MakeLocal(1072, "Simple Button");
96 MakeLocal(1073, "Sound Trap");
97 MakeLocal(1323, "Trigger Delay");
100 if (NEED_UPDATE("eng2.mis", 1))
102 // This exp cookie was somehow strangely set up
103 ObjID obj
= RealObj(934, "Small BP Pile");
105 gPropAutoPickup
->Set(obj
, FALSE
);
107 // The Many ride needs to use the ChangeInterfaceMany script,
108 // instead of ChangeInterface
109 obj
= RealObj(1563, "Marker");
112 AutoAppIPtr(PropertyManager
);
113 sScriptProp
*pScripts
;
114 IScriptProperty
*pScriptProperty
=
115 (IScriptProperty
*)(pPropertyManager
->GetPropertyNamed("Scripts"));
116 if (pScriptProperty
->Get(obj
, &pScripts
))
118 strcpy(pScripts
->script
[0], "ChangeInterfaceMany");
119 pScriptProperty
->Set(obj
, pScripts
);
124 if (NEED_UPDATE("ops4.mis", 1))
126 // Needs a multiplayer respawn marker; we just rename one of the
128 ObjID obj
= RealObj(343, "Marker");
130 pObjectSystem
->NameObject(obj
, "Multiplayer Respawn");
132 // These are cardslots for a pair of locked security doors. In
133 // retrospect, the key for these is much too separated from the
134 // doors themselves, and they're plot-blocking. So unlock them.
135 obj
= RealObj(620, "Card slot");
137 ObjSetSelfLocked(obj
, FALSE
);
138 obj
= RealObj(619, "Card slot");
140 ObjSetSelfLocked(obj
, FALSE
);
143 if (NEED_UPDATE("rec1.mis", 1))
145 // This is a Transmitter Tower -- actually a fancy keypad -- and
146 // should be frobLocally
147 ObjID obj
= RealObj(89, "Transmitter Tower Off");
149 SetFrobHandler(obj
, kFrobHandlerLocal
);
152 if (NEED_UPDATE("rick3.mis", 1))
154 // This is the "escape tunnel". When the shuttle launches to go to
155 // the Many, we *actually* move the tunnel. But it wasn't set up
156 // properly -- the thing needs the moving terrain property on it...
157 ObjID obj
= RealObj(120, "EscapeTunnel");
160 cMovingTerrainProp pMTProp
;
161 pMTProp
.active
= FALSE
;
162 pMTProp
.prev_state
= FALSE
;
163 g_pMovingTerrainProperty
->Set(obj
, &pMTProp
);
167 if (NEED_UPDATE("command2.mis", 1))
169 // This is the escape pod that leaves just as we try to get to it.
170 // Again, it needs the moving terrain property set...
171 ObjID obj
= RealObj(301, "Escape Pod");
174 cMovingTerrainProp pMTProp
;
175 pMTProp
.active
= FALSE
;
176 pMTProp
.prev_state
= FALSE
;
177 g_pMovingTerrainProperty
->Set(obj
, &pMTProp
);
181 if (NEED_UPDATE("medsci1.mis", 1))
183 // The very first OG is controlled by a pseudoscript; handoff
184 // interferes with that. The result is that, if the client sets
185 // him off, the OG begins to run at him, then turns around and
186 // forgets about him. Better to not hand off, and have poor aim,
187 // than this dumbness.
188 ObjID obj
= RealObj(1383, "OG-Pipe");
191 g_pAINoHandoffProperty
->Set(obj
, TRUE
);
195 if (NEED_UPDATE("many.mis", 1))
197 // One of these spawn traps is way the heck too hard, and people
198 // have been complaining about it. So switch it from generating
199 // mostly midwives and a few rumblers, to just rumblers.
200 ObjID obj
= RealObj(1489, "RandMonsterGen");
203 sSpawnInfo
*pSpawnInfo
;
204 if (gPropSpawn
->Get(obj
, &pSpawnInfo
))
206 pSpawnInfo
->m_odds
[0] = 0; // Chance of midwife
207 pSpawnInfo
->m_odds
[1] = 100; // Chance of rumbler
208 gPropSpawn
->Set(obj
, pSpawnInfo
);
213 if (NEED_UPDATE("rec2.mis", 1))
215 // One of the LandingPoint markers, for player 3, is slightly
216 // embedded in the wall. As a result, he can't move when he
217 // teleports in. Shove it a foot in:
218 ObjID obj
= RealObj(268, "Marker");
221 ObjPos
*pos
= ObjPosGet(obj
);
224 // X is about 41.6; should be about 40.6:
226 ObjTranslate(obj
, &(pos
->loc
.vec
));