macro_special_objects.c (13428B)
1 #include <PR/ultratypes.h> 2 3 #include "sm64.h" 4 #include "object_helpers.h" 5 #include "macro_special_objects.h" 6 #include "object_list_processor.h" 7 #include "behavior_data.h" 8 9 #include "macro_presets.inc.c" 10 #include "special_presets.inc.c" 11 12 /* 13 * Converts the rotation value supplied by macro objects into one 14 * that can be used by in-game objects. 15 */ 16 s16 convert_rotation(s16 inRotation) { 17 u16 rotation = ((u16)(inRotation & 0xFF)); 18 rotation <<= 8; 19 20 if (rotation == 0x3F00) { 21 rotation = 0x4000; 22 } 23 24 if (rotation == 0x7F00) { 25 rotation = 0x8000; 26 } 27 28 if (rotation == 0xBF00) { 29 rotation = 0xC000; 30 } 31 32 if (rotation == 0xFF00) { 33 rotation = 0x0000; 34 } 35 36 return (s16) rotation; 37 } 38 39 /* 40 * Spawns an object at an absolute location with rotation around the y-axis and 41 * parameters filling up the upper 2 bytes of newObj->oBhvParams. 42 * The object will not spawn if 'behavior' is NULL. 43 */ 44 void spawn_macro_abs_yrot_2params(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 ry, s16 params) { 45 if (behavior != NULL) { 46 struct Object *newObj = spawn_object_abs_with_rot( 47 &gMacroObjectDefaultParent, 0, model, behavior, x, y, z, 0, convert_rotation(ry), 0); 48 newObj->oBhvParams = ((u32) params) << 16; 49 } 50 } 51 52 /* 53 * Spawns an object at an absolute location with rotation around the y-axis and 54 * a single parameter filling up the upper byte of newObj->oBhvParams. 55 * The object will not spawn if 'behavior' is NULL. 56 */ 57 void spawn_macro_abs_yrot_param1(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 ry, s16 param) { 58 if (behavior != NULL) { 59 struct Object *newObj = spawn_object_abs_with_rot( 60 &gMacroObjectDefaultParent, 0, model, behavior, x, y, z, 0, convert_rotation(ry), 0); 61 newObj->oBhvParams = ((u32) param) << 24; 62 } 63 } 64 65 /* 66 * Spawns an object at an absolute location with currently 3 unknown variables that get converted to 67 * floats. Oddly enough, this function doesn't care if 'behavior' is NULL or not. 68 */ 69 void spawn_macro_abs_special(s32 model, const BehaviorScript *behavior, s16 x, s16 y, s16 z, s16 unkA, s16 unkB, 70 s16 unkC) { 71 struct Object *newObj = 72 spawn_object_abs_with_rot(&gMacroObjectDefaultParent, 0, model, behavior, x, y, z, 0, 0, 0); 73 74 // Are all three of these values unused? 75 newObj->oMacroUnk108 = (f32) unkA; 76 newObj->oMacroUnk10C = (f32) unkB; 77 newObj->oMacroUnk110 = (f32) unkC; 78 } 79 80 #define MACRO_OBJ_Y_ROT 0 81 #define MACRO_OBJ_X 1 82 #define MACRO_OBJ_Y 2 83 #define MACRO_OBJ_Z 3 84 #define MACRO_OBJ_PARAMS 4 85 86 UNUSED static void spawn_macro_coin_unknown(const BehaviorScript *behavior, s16 objInfo[]) { 87 struct Object *coin; 88 s16 model = bhvYellowCoin == behavior ? MODEL_YELLOW_COIN : MODEL_NONE; 89 90 coin = spawn_object_abs_with_rot(&gMacroObjectDefaultParent, 0, model, behavior, 91 objInfo[MACRO_OBJ_X], objInfo[MACRO_OBJ_Y], objInfo[MACRO_OBJ_Z], 92 0, convert_rotation(objInfo[MACRO_OBJ_Y_ROT]), 0); 93 coin->oUnusedBhvParams = objInfo[MACRO_OBJ_PARAMS]; 94 coin->oBhvParams = (objInfo[MACRO_OBJ_PARAMS] & 0xFF) >> 16; 95 } 96 97 struct LoadedPreset { 98 /* 0x00 */ const BehaviorScript *behavior; 99 /* 0x04 */ s16 param; // huh? why does the below function swap these.. just use the struct.. 100 /* 0x06 */ s16 model; 101 }; 102 103 void spawn_macro_objects(s16 areaIndex, s16 *macroObjList) { 104 UNUSED u8 filler[4]; 105 s32 presetID; 106 107 s16 macroObject[5]; // see the 5 #define statements above 108 struct Object *newObj; 109 struct LoadedPreset preset; 110 111 gMacroObjectDefaultParent.header.gfx.areaIndex = areaIndex; 112 gMacroObjectDefaultParent.header.gfx.activeAreaIndex = areaIndex; 113 114 while (TRUE) { 115 if (*macroObjList == -1) { // An encountered value of -1 means the list has ended. 116 break; 117 } 118 119 presetID = (*macroObjList & 0x1FF) - 31; // Preset identifier for sMacroObjectPresets array 120 121 if (presetID < 0) { 122 break; 123 } 124 125 // Set macro object properties from the list 126 macroObject[MACRO_OBJ_Y_ROT] = ((*macroObjList++ >> 9) & 0x7F) << 1; // Y-Rotation 127 macroObject[MACRO_OBJ_X] = *macroObjList++; // X position 128 macroObject[MACRO_OBJ_Y] = *macroObjList++; // Y position 129 macroObject[MACRO_OBJ_Z] = *macroObjList++; // Z position 130 macroObject[MACRO_OBJ_PARAMS] = *macroObjList++; // Behavior params 131 132 // Get the preset values from the sMacroObjectPresets list. 133 preset.model = sMacroObjectPresets[presetID].model; 134 preset.behavior = sMacroObjectPresets[presetID].behavior; 135 preset.param = sMacroObjectPresets[presetID].param; 136 137 if (preset.param != 0) { 138 macroObject[MACRO_OBJ_PARAMS] = 139 (macroObject[MACRO_OBJ_PARAMS] & 0xFF00) + (preset.param & 0x00FF); 140 } 141 142 // If object has been killed, prevent it from respawning 143 if (((macroObject[MACRO_OBJ_PARAMS] >> 8) & RESPAWN_INFO_DONT_RESPAWN) 144 != RESPAWN_INFO_DONT_RESPAWN) { 145 // Spawn the new macro object. 146 newObj = spawn_object_abs_with_rot( 147 &gMacroObjectDefaultParent, // Parent object 148 0, // Unused 149 preset.model, // Model ID 150 preset.behavior, // Behavior address 151 macroObject[MACRO_OBJ_X], // X-position 152 macroObject[MACRO_OBJ_Y], // Y-position 153 macroObject[MACRO_OBJ_Z], // Z-position 154 0, // X-rotation 155 convert_rotation(macroObject[MACRO_OBJ_Y_ROT]), // Y-rotation 156 0 // Z-rotation 157 ); 158 159 newObj->oUnusedBhvParams = macroObject[MACRO_OBJ_PARAMS]; 160 newObj->oBhvParams = ((macroObject[MACRO_OBJ_PARAMS] & 0x00FF) << 16) 161 + (macroObject[MACRO_OBJ_PARAMS] & 0xFF00); 162 newObj->oBhvParams2ndByte = macroObject[MACRO_OBJ_PARAMS] & 0x00FF; 163 newObj->respawnInfoType = RESPAWN_INFO_TYPE_16; 164 newObj->respawnInfo = macroObjList - 1; 165 newObj->parentObj = newObj; 166 } 167 } 168 } 169 170 void spawn_macro_objects_hardcoded(s16 areaIndex, s16 *macroObjList) { 171 UNUSED u8 filler1[8]; 172 173 // This version of macroObjList has the preset and Y-Rotation separated, 174 // and lacks behavior params. Might be an early version of the macro object list? 175 s16 macroObjX; 176 s16 macroObjY; 177 s16 macroObjZ; 178 s16 macroObjPreset; 179 s16 macroObjRY; // Y Rotation 180 181 UNUSED u8 filler2[10]; 182 183 gMacroObjectDefaultParent.header.gfx.areaIndex = areaIndex; 184 gMacroObjectDefaultParent.header.gfx.activeAreaIndex = areaIndex; 185 186 while (TRUE) { 187 macroObjPreset = *macroObjList++; 188 189 if (macroObjPreset < 0) { 190 break; 191 } 192 193 macroObjX = *macroObjList++; 194 macroObjY = *macroObjList++; 195 macroObjZ = *macroObjList++; 196 macroObjRY = *macroObjList++; 197 198 // Spawn objects based on hardcoded presets, and most seem to be for Big Boo's Haunt. 199 // However, BBH doesn't use this function so this might just be an early test? 200 switch (macroObjPreset) { 201 case 0: 202 spawn_macro_abs_yrot_2params(MODEL_NONE, bhvBooStaircase, macroObjX, macroObjY, 203 macroObjZ, macroObjRY, 0); 204 break; 205 case 1: 206 spawn_macro_abs_yrot_2params(MODEL_BBH_TILTING_FLOOR_PLATFORM, 207 bhvBBHTiltingTrapPlatform, macroObjX, macroObjY, macroObjZ, 208 macroObjRY, 0); 209 break; 210 case 2: 211 spawn_macro_abs_yrot_2params(MODEL_BBH_TUMBLING_PLATFORM, bhvBBHTumblingBridge, 212 macroObjX, macroObjY, macroObjZ, macroObjRY, 0); 213 break; 214 case 3: 215 spawn_macro_abs_yrot_2params(MODEL_BBH_MOVING_BOOKSHELF, bhvHauntedBookshelf, macroObjX, 216 macroObjY, macroObjZ, macroObjRY, 0); 217 break; 218 case 4: 219 spawn_macro_abs_yrot_2params(MODEL_BBH_MESH_ELEVATOR, bhvMeshElevator, macroObjX, 220 macroObjY, macroObjZ, macroObjRY, 0); 221 break; 222 case 20: 223 spawn_macro_abs_yrot_2params(MODEL_YELLOW_COIN, bhvYellowCoin, macroObjX, macroObjY, 224 macroObjZ, macroObjRY, 0); 225 break; 226 case 21: 227 spawn_macro_abs_yrot_2params(MODEL_YELLOW_COIN, bhvYellowCoin, macroObjX, macroObjY, 228 macroObjZ, macroObjRY, 0); 229 break; 230 default: 231 break; 232 } 233 } 234 } 235 236 void spawn_special_objects(s16 areaIndex, TerrainData **specialObjList) { 237 s32 numOfSpecialObjects; 238 s32 i; 239 s32 offset; 240 s16 x; 241 s16 y; 242 s16 z; 243 s16 extraParams[4]; 244 u8 model; 245 u8 type; 246 u8 presetID; 247 u8 defaultParam; 248 const BehaviorScript *behavior; 249 250 numOfSpecialObjects = **specialObjList; 251 (*specialObjList)++; 252 253 gMacroObjectDefaultParent.header.gfx.areaIndex = areaIndex; 254 gMacroObjectDefaultParent.header.gfx.activeAreaIndex = areaIndex; 255 256 for (i = 0; i < numOfSpecialObjects; i++) { 257 presetID = (u8) **specialObjList; 258 (*specialObjList)++; 259 x = **specialObjList; 260 (*specialObjList)++; 261 y = **specialObjList; 262 (*specialObjList)++; 263 z = **specialObjList; 264 (*specialObjList)++; 265 266 offset = 0; 267 while (TRUE) { 268 if (sSpecialObjectPresets[offset].presetID == presetID) { 269 break; 270 } 271 272 if (sSpecialObjectPresets[offset].presetID == special_null_end) { 273 } 274 275 offset++; 276 } 277 278 model = sSpecialObjectPresets[offset].model; 279 behavior = sSpecialObjectPresets[offset].behavior; 280 type = sSpecialObjectPresets[offset].type; 281 defaultParam = sSpecialObjectPresets[offset].defParam; 282 283 switch (type) { 284 case SPTYPE_NO_YROT_OR_PARAMS: 285 spawn_macro_abs_yrot_2params(model, behavior, x, y, z, 0, 0); 286 break; 287 case SPTYPE_YROT_NO_PARAMS: 288 extraParams[0] = **specialObjList; // Y-rotation 289 (*specialObjList)++; 290 spawn_macro_abs_yrot_2params(model, behavior, x, y, z, extraParams[0], 0); 291 break; 292 case SPTYPE_PARAMS_AND_YROT: 293 extraParams[0] = **specialObjList; // Y-rotation 294 (*specialObjList)++; 295 extraParams[1] = **specialObjList; // Params 296 (*specialObjList)++; 297 spawn_macro_abs_yrot_2params(model, behavior, x, y, z, extraParams[0], extraParams[1]); 298 break; 299 case SPTYPE_UNKNOWN: 300 extraParams[0] = 301 **specialObjList; // Unknown, gets put into obj->oMacroUnk108 as a float 302 (*specialObjList)++; 303 extraParams[1] = 304 **specialObjList; // Unknown, gets put into obj->oMacroUnk10C as a float 305 (*specialObjList)++; 306 extraParams[2] = 307 **specialObjList; // Unknown, gets put into obj->oMacroUnk110 as a float 308 (*specialObjList)++; 309 spawn_macro_abs_special(model, behavior, x, y, z, extraParams[0], extraParams[1], 310 extraParams[2]); 311 break; 312 case SPTYPE_DEF_PARAM_AND_YROT: 313 extraParams[0] = **specialObjList; // Y-rotation 314 (*specialObjList)++; 315 spawn_macro_abs_yrot_param1(model, behavior, x, y, z, extraParams[0], defaultParam); 316 break; 317 default: 318 break; 319 } 320 } 321 } 322 323 #ifdef NO_SEGMENTED_MEMORY 324 u32 get_special_objects_size(s16 *data) { 325 s16 *startPos = data; 326 s32 numOfSpecialObjects; 327 s32 i; 328 u8 presetID; 329 s32 offset; 330 331 numOfSpecialObjects = *data++; 332 333 for (i = 0; i < numOfSpecialObjects; i++) { 334 presetID = (u8) *data++; 335 data += 3; 336 offset = 0; 337 338 while (TRUE) { 339 if (sSpecialObjectPresets[offset].presetID == presetID) { 340 break; 341 } 342 offset++; 343 } 344 345 switch (sSpecialObjectPresets[offset].type) { 346 case SPTYPE_NO_YROT_OR_PARAMS: 347 break; 348 case SPTYPE_YROT_NO_PARAMS: 349 data++; 350 break; 351 case SPTYPE_PARAMS_AND_YROT: 352 data += 2; 353 break; 354 case SPTYPE_UNKNOWN: 355 data += 3; 356 break; 357 case SPTYPE_DEF_PARAM_AND_YROT: 358 data++; 359 break; 360 default: 361 break; 362 } 363 } 364 365 return data - startPos; 366 } 367 #endif