mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-21 19:45:10 +00:00
Fix several more possible crashes from the Lua API
This commit is contained in:
parent
ed163203d8
commit
60d70d0d38
28 changed files with 87 additions and 47 deletions
14
Makefile
14
Makefile
|
@ -952,9 +952,17 @@ ifeq ($(WINDOWS_BUILD),999)
|
|||
endif
|
||||
|
||||
ifeq ($(ASAN),1)
|
||||
EXTRA_CFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb
|
||||
EXTRA_CPP_FLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb
|
||||
LDFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -static-libasan
|
||||
|
||||
ifeq ($(COMPILER),gcc)
|
||||
EXTRA_CFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb
|
||||
EXTRA_CPP_FLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb
|
||||
LDFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -static-libasan
|
||||
else ifeq ($(COMPILER),clang)
|
||||
EXTRA_CFLAGS += -fsanitize=address -fsanitize=undefined -ggdb
|
||||
EXTRA_CPP_FLAGS += -fsanitize=address -fsanitize=undefined -ggdb
|
||||
LDFLAGS += -fsanitize=address -fsanitize=undefined
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
# Coop specific libraries
|
||||
|
|
|
@ -93,7 +93,7 @@ override_field_immutable = {
|
|||
"GlobalObjectAnimations": [ "*"],
|
||||
"SpawnParticlesInfo": [ "model" ],
|
||||
"MarioBodyState": [ "updateTorsoTime" ],
|
||||
"Area": [ "localAreaTimer", "nextSyncID", "unk04" ],
|
||||
"Area": [ "localAreaTimer", "nextSyncID", "unk04", "objectSpawnInfos", "paintingWarpNodes", "warpNodes" ],
|
||||
"Mod": [ "*" ],
|
||||
"ModFile": [ "*" ],
|
||||
"BassAudio": [ "*" ],
|
||||
|
|
|
@ -84,6 +84,9 @@ void DynOS_Anim_Swap(void *aPtr) {
|
|||
if (_AnimIndex == -1) {
|
||||
return;
|
||||
}
|
||||
if (_AnimIndex >= _GfxData->mAnimationTable.Count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Animation data
|
||||
const AnimData *_AnimData = (const AnimData *) _GfxData->mAnimationTable[_AnimIndex].second;
|
||||
|
|
|
@ -13,7 +13,8 @@ struct ScheduledFreePool {
|
|||
};
|
||||
|
||||
static struct DynamicPool* sModelPools[MODEL_POOL_MAX] = { 0 };
|
||||
static std::map<void*, struct GraphNode*> sModelMap[MODEL_POOL_MAX];
|
||||
static std::map<void*, struct GraphNode*> sGraphNodeMap[MODEL_POOL_MAX];
|
||||
static std::map<u32, struct GraphNode*> sModelIdMap;
|
||||
static std::vector<struct ScheduledFreePool> sPoolsToFree;
|
||||
|
||||
struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset) {
|
||||
|
@ -26,7 +27,7 @@ struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset) {
|
|||
}
|
||||
|
||||
// check map
|
||||
auto& map = sModelMap[aModelPool];
|
||||
auto& map = sGraphNodeMap[aModelPool];
|
||||
if (map.count(aAsset)) {
|
||||
return map[aAsset];
|
||||
}
|
||||
|
@ -49,7 +50,7 @@ struct GraphNode* DynOS_Model_LoadDl(enum ModelPool aModelPool, u8 aLayer, void*
|
|||
}
|
||||
|
||||
// check map
|
||||
auto& map = sModelMap[aModelPool];
|
||||
auto& map = sGraphNodeMap[aModelPool];
|
||||
if (map.count(aAsset)) {
|
||||
return map[aAsset];
|
||||
}
|
||||
|
@ -75,7 +76,7 @@ void DynOS_Model_ClearPool(enum ModelPool aModelPool) {
|
|||
sModelPools[aModelPool] = NULL;
|
||||
|
||||
// clear map
|
||||
auto& map = sModelMap[aModelPool];
|
||||
auto& map = sGraphNodeMap[aModelPool];
|
||||
map.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -145,12 +145,12 @@
|
|||
| nextSyncID | `integer` | read-only |
|
||||
| numRedCoins | `integer` | |
|
||||
| numSecrets | `integer` | |
|
||||
| objectSpawnInfos | [SpawnInfo](structs.md#SpawnInfo) | |
|
||||
| paintingWarpNodes | [WarpNode](structs.md#WarpNode) | |
|
||||
| objectSpawnInfos | [SpawnInfo](structs.md#SpawnInfo) | read-only |
|
||||
| paintingWarpNodes | [WarpNode](structs.md#WarpNode) | read-only |
|
||||
| surfaceRooms | `Pointer` <`integer`> | read-only |
|
||||
| terrainData | `Pointer` <`integer`> | read-only |
|
||||
| terrainType | `integer` | |
|
||||
| warpNodes | [ObjectWarpNode](structs.md#ObjectWarpNode) | |
|
||||
| warpNodes | [ObjectWarpNode](structs.md#ObjectWarpNode) | read-only |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
|
|
|
@ -1064,6 +1064,7 @@ void audio_list_push_front(struct AudioListItem *list, struct AudioListItem *ite
|
|||
}
|
||||
|
||||
void audio_list_remove(struct AudioListItem *item) {
|
||||
if (!item) { return; }
|
||||
// remove 'item' from the list it's in, if any
|
||||
if (item->prev == NULL) {
|
||||
eu_stubbed_printf_0("Already Cut\n");
|
||||
|
|
|
@ -25,7 +25,9 @@ static void handle_merry_go_round_music(void) {
|
|||
struct Object *marioObject = gMarioObjects[0];
|
||||
u16 marioFloorType = 0;
|
||||
|
||||
find_floor(marioObject->oPosX, marioObject->oPosY, marioObject->oPosZ, &marioFloor);
|
||||
if (marioObject) {
|
||||
find_floor(marioObject->oPosX, marioObject->oPosY, marioObject->oPosZ, &marioFloor);
|
||||
}
|
||||
|
||||
if (marioFloor != NULL) {
|
||||
marioFloorType = marioFloor->type;
|
||||
|
|
|
@ -130,7 +130,7 @@ static void beta_boo_key_drop(void) {
|
|||
|
||||
// Make the key move laterally away from Mario at 3 units/frame
|
||||
// (as if he transferred kinetic energy to it)
|
||||
velocityDirection = gMarioObject->oMoveAngleYaw;
|
||||
velocityDirection = gMarioObject ? gMarioObject->oMoveAngleYaw : 0;
|
||||
velocityMagnitude = 3.0f;
|
||||
|
||||
o->oVelX = sins(velocityDirection) * velocityMagnitude;
|
||||
|
|
|
@ -75,7 +75,7 @@ void bhv_beta_trampoline_top_loop(void) {
|
|||
// Since the trampoline never moves, this doesn't do anything.
|
||||
// Maybe they intended to decrease the trampoline's position
|
||||
// when Mario's on it in this if statement?
|
||||
if (gMarioObject->platform == o) {
|
||||
if (gMarioObject && gMarioObject->platform == o) {
|
||||
o->oBetaTrampolineMarioOnTrampoline = TRUE;
|
||||
} else {
|
||||
o->oBetaTrampolineMarioOnTrampoline = FALSE;
|
||||
|
|
|
@ -135,7 +135,7 @@ void bhv_blue_coin_switch_loop(void) {
|
|||
case BLUE_COIN_SWITCH_ACT_IDLE:
|
||||
// If Mario is on the switch and has ground-pounded,
|
||||
// recede and get ready to start ticking.
|
||||
if (gMarioObject->platform == o) {
|
||||
if (gMarioObject && gMarioObject->platform == o) {
|
||||
if (determine_interaction(&gMarioStates[0], o) & INT_GROUND_POUND) {
|
||||
// Set to BLUE_COIN_SWITCH_ACT_RECEDING
|
||||
o->oAction++;
|
||||
|
@ -164,7 +164,9 @@ void bhv_blue_coin_switch_loop(void) {
|
|||
// Set to BLUE_COIN_SWITCH_ACT_TICKING
|
||||
o->oAction++;
|
||||
// ???
|
||||
o->oPosY = gMarioObject->oPosY - 40.0f;
|
||||
if (gMarioObject) {
|
||||
o->oPosY = gMarioObject->oPosY - 40.0f;
|
||||
}
|
||||
|
||||
// Spawn particles. There's a function that calls this same function
|
||||
// with the same arguments, spawn_mist_particles, why didn't they just call that?
|
||||
|
|
|
@ -1029,7 +1029,7 @@ void bhv_boo_in_castle_loop(void) {
|
|||
}
|
||||
|
||||
void bhv_boo_boss_spawned_bridge_loop(void) {
|
||||
f32 targetY;
|
||||
f32 targetY = 0;
|
||||
|
||||
switch (o->oBehParams2ndByte) {
|
||||
case 1:
|
||||
|
|
|
@ -75,7 +75,7 @@ void opened_cannon_act_6(void) {
|
|||
o->oMoveAngleYaw = sins(o->oCannonUnkF4) * 0x4000 + ((s16)(o->oBehParams2ndByte << 8));
|
||||
o->oCannonUnkF4 += 0x400;
|
||||
} else if (o->oTimer < 26) {
|
||||
} else if (o->oCannonPlayerIndex < MAX_PLAYERS) {
|
||||
} else if (o->oCannonPlayerIndex >= 0 && o->oCannonPlayerIndex < MAX_PLAYERS) {
|
||||
struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex];
|
||||
if (controlledBy && controlledBy->marioObj != NULL) {
|
||||
controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw;
|
||||
|
@ -110,7 +110,7 @@ void opened_cannon_act_1(void) {
|
|||
if (o->oCannonPlayerIndex == 0) {
|
||||
cur_obj_become_intangible();
|
||||
cur_obj_disable_rendering();
|
||||
} else if (o->oCannonPlayerIndex < MAX_PLAYERS) {
|
||||
} else if (o->oCannonPlayerIndex >= 0 && o->oCannonPlayerIndex < MAX_PLAYERS) {
|
||||
struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex];
|
||||
o->oMoveAnglePitch = 14563 + controlledBy->faceAngle[0] * -0.5f;
|
||||
if (controlledBy->marioObj != NULL) {
|
||||
|
|
|
@ -450,7 +450,6 @@ static void chain_chomp_act_move(void) {
|
|||
*/
|
||||
static void chain_chomp_act_unload_chain(void) {
|
||||
cur_obj_hide();
|
||||
dynamic_pool_free(gLevelPool, o->oChainChompSegments);
|
||||
|
||||
o->oAction = CHAIN_CHOMP_ACT_UNINITIALIZED;
|
||||
|
||||
|
|
|
@ -244,7 +244,7 @@ void coin_inside_boo_act_0(void) {
|
|||
obj_copy_pos(o, parent);
|
||||
if (parent->oBooDeathStatus == BOO_DEATH_STATUS_DYING) {
|
||||
o->oAction = 1;
|
||||
s16 sp26 = gMarioObject->oMoveAngleYaw;
|
||||
s16 sp26 = gMarioObject ? gMarioObject->oMoveAngleYaw : 0;
|
||||
f32 sp20 = 3.0f;
|
||||
o->oVelX = sins(sp26) * sp20;
|
||||
o->oVelZ = coss(sp26) * sp20;
|
||||
|
|
|
@ -8,7 +8,9 @@ void bhv_hidden_star_init(void) {
|
|||
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
}
|
||||
|
||||
o->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count;
|
||||
if (gCurrentArea) {
|
||||
o->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count;
|
||||
}
|
||||
|
||||
// We haven't interacted with a player yet.
|
||||
// We also don't sync this as not only is it not required
|
||||
|
@ -34,7 +36,7 @@ void bhv_hidden_star_init(void) {
|
|||
void bhv_hidden_star_loop(void) {
|
||||
switch (o->oAction) {
|
||||
case 0:
|
||||
if (o->oHiddenStarTriggerCounter >= gCurrentArea->numSecrets) {
|
||||
if (gCurrentArea && o->oHiddenStarTriggerCounter >= gCurrentArea->numSecrets) {
|
||||
o->oAction = 1;
|
||||
}
|
||||
break;
|
||||
|
@ -63,7 +65,9 @@ void bhv_hidden_star_trigger_loop(void) {
|
|||
if (hiddenStar != NULL) {
|
||||
|
||||
s16 count = (count_objects_with_behavior(bhvHiddenStarTrigger) - 1);
|
||||
hiddenStar->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count;
|
||||
if (gCurrentArea) {
|
||||
hiddenStar->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count;
|
||||
}
|
||||
spawn_orange_number(hiddenStar->oHiddenStarTriggerCounter, 0, 0, 0);
|
||||
|
||||
// Set the last person who interacted with a secret to the
|
||||
|
@ -98,7 +102,7 @@ void bhv_hidden_star_trigger_loop(void) {
|
|||
void bhv_bowser_course_red_coin_star_loop(void) {
|
||||
switch (o->oAction) {
|
||||
case 0:
|
||||
if (o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) {
|
||||
if (gCurrentArea && o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) {
|
||||
o->oAction = 1;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -39,8 +39,9 @@ void bhv_ship_part_3_loop(void) {
|
|||
o->oFaceAngleRoll = sins(o->oShipPart3UnkF8) * 1024.0f;
|
||||
o->oAngleVelPitch = o->oFaceAnglePitch - sp1E;
|
||||
o->oAngleVelRoll = o->oFaceAngleRoll - sp1C;
|
||||
if (gMarioObject->oPosY > 1000.0f)
|
||||
if (gMarioObject && gMarioObject->oPosY > 1000.0f) {
|
||||
cur_obj_play_sound_1(SOUND_ENV_BOAT_ROCKING1);
|
||||
}
|
||||
}
|
||||
|
||||
void bhv_jrb_sliding_box_loop(void) {
|
||||
|
@ -103,13 +104,18 @@ void bhv_jrb_sliding_box_loop(void) {
|
|||
o->oJrbSlidingBoxUnkFC = sins(o->oJrbSlidingBoxUnkF8) * 20.0f;
|
||||
o->oJrbSlidingBoxUnkF8 += 0x100;
|
||||
o->oParentRelativePosZ += o->oJrbSlidingBoxUnkFC;
|
||||
if (gMarioObject->oPosY > 1000.0f)
|
||||
if (absf(o->oJrbSlidingBoxUnkFC) > 3.0f)
|
||||
if (gMarioObject && gMarioObject->oPosY > 1000.0f) {
|
||||
if (absf(o->oJrbSlidingBoxUnkFC) > 3.0f) {
|
||||
cur_obj_play_sound_1(SOUND_AIR_ROUGH_SLIDE);
|
||||
}
|
||||
}
|
||||
|
||||
obj_set_hitbox(o, &sSkullSlidingBoxHitbox);
|
||||
if (!(o->oJrbSlidingBoxUnkF8 & 0x7FFF))
|
||||
if (!(o->oJrbSlidingBoxUnkF8 & 0x7FFF)) {
|
||||
cur_obj_become_tangible();
|
||||
if (obj_check_if_collided_with_object(o, gMarioObject)) {
|
||||
}
|
||||
|
||||
if (gMarioObject && obj_check_if_collided_with_object(o, gMarioObject)) {
|
||||
o->oInteractStatus = 0;
|
||||
cur_obj_become_intangible();
|
||||
}
|
||||
|
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
void bhv_pole_base_loop(void) {
|
||||
if (!gMarioObject) { return; }
|
||||
if (o->oPosY - 10.0f < gMarioObject->oPosY
|
||||
&& gMarioObject->oPosY < o->oPosY + o->hitboxHeight + 30.0f)
|
||||
if (o->oTimer > 10)
|
||||
if (!(gMarioStates[0].action & MARIO_PUNCHING))
|
||||
if (o->oPosY - 10.0f < gMarioObject->oPosY && gMarioObject->oPosY < o->oPosY + o->hitboxHeight + 30.0f) {
|
||||
if (o->oTimer > 10) {
|
||||
if (!(gMarioStates[0].action & MARIO_PUNCHING)) {
|
||||
cur_obj_push_mario_away(70.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ void bhv_purple_switch_loop(void) {
|
|||
case PURPLE_SWITCH_IDLE:
|
||||
cur_obj_set_model(smlua_model_util_load(E_MODEL_PURPLE_SWITCH));
|
||||
cur_obj_scale(1.5f);
|
||||
if (gMarioObject->platform == o && !(gMarioStates[0].action & MARIO_UNKNOWN_13)) {
|
||||
if (gMarioObject && gMarioObject->platform == o && !(gMarioStates[0].action & MARIO_UNKNOWN_13)) {
|
||||
if (lateral_dist_between_objects(o, gMarioObject) < 127.5) {
|
||||
o->oAction = PURPLE_SWITCH_PRESSED;
|
||||
network_send_object(o);
|
||||
|
|
|
@ -50,7 +50,9 @@ void bhv_red_coin_loop(void) {
|
|||
// ...and there is a red coin star in the level...
|
||||
if (o->parentObj != NULL) {
|
||||
s16 redCoins = count_objects_with_behavior(bhvRedCoin) - 1;
|
||||
o->parentObj->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins;
|
||||
if (gCurrentArea) {
|
||||
o->parentObj->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins;
|
||||
}
|
||||
|
||||
// Set the last person who interacted with a red coin to the
|
||||
// parent so only they get the star cutscene.
|
||||
|
|
|
@ -288,7 +288,9 @@ void bhv_hidden_red_coin_star_init(void) {
|
|||
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
}
|
||||
|
||||
o->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins;
|
||||
if (gCurrentArea) {
|
||||
o->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins;
|
||||
}
|
||||
|
||||
// We haven't interacted with a player yet.
|
||||
// We also don't sync this as not only is it not required
|
||||
|
@ -313,7 +315,7 @@ void bhv_hidden_red_coin_star_init(void) {
|
|||
void bhv_hidden_red_coin_star_loop(void) {
|
||||
switch (o->oAction) {
|
||||
case 0:
|
||||
if (o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) {
|
||||
if (gCurrentArea && o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) {
|
||||
o->oAction = 1;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -21,7 +21,7 @@ void bhv_wf_elevator_tower_platform_loop(void) {
|
|||
|
||||
switch (o->oAction) {
|
||||
case 0:
|
||||
if (gMarioObject->platform == o) {
|
||||
if (gMarioObject && gMarioObject->platform == o) {
|
||||
o->oAction++;
|
||||
network_send_object(o);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,13 @@ void bhv_ttc_treadmill_update(void) {
|
|||
approach_f32_ptr(&o->oTTCTreadmillSpeed, o->oTTCTreadmillTargetSpeed, 10.0f);
|
||||
}
|
||||
|
||||
*o->oTTCTreadmillBigSurface = *o->oTTCTreadmillSmallSurface = o->oTTCTreadmillSpeed;
|
||||
if (o->oTTCTreadmillSmallSurface) {
|
||||
*o->oTTCTreadmillSmallSurface = o->oTTCTreadmillSpeed;
|
||||
}
|
||||
|
||||
if (o->oTTCTreadmillBigSurface) {
|
||||
*o->oTTCTreadmillBigSurface = o->oTTCTreadmillSpeed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5429,7 +5429,7 @@ void warp_camera(f32 displacementX, f32 displacementY, f32 displacementZ) {
|
|||
struct LinearTransitionPoint *start = &sModeInfo.transitionStart;
|
||||
struct LinearTransitionPoint *end = &sModeInfo.transitionEnd;
|
||||
|
||||
gCurrLevelArea = gCurrLevelNum * 16 + gCurrentArea->index;
|
||||
gCurrLevelArea = gCurrLevelNum * 16 + (gCurrentArea ? gCurrentArea->index : 0);
|
||||
displacement[0] = displacementX;
|
||||
displacement[1] = displacementY;
|
||||
displacement[2] = displacementZ;
|
||||
|
|
|
@ -865,6 +865,7 @@ void update_mario_sound_and_camera(struct MarioState *m) {
|
|||
|
||||
// only update for local player
|
||||
if (m != &gMarioStates[0]) { return; }
|
||||
if (!m->area || !m->area->camera) { return; }
|
||||
|
||||
u32 action = m->action;
|
||||
s32 camPreset = m->area->camera->mode;
|
||||
|
@ -1332,7 +1333,7 @@ s32 check_common_hold_action_exits(struct MarioState *m) {
|
|||
*/
|
||||
s32 transition_submerged_to_walking(struct MarioState *m) {
|
||||
if (!m) { return FALSE; }
|
||||
if (m->playerIndex == 0) {
|
||||
if (m->playerIndex == 0 && m->area && m->area->camera) {
|
||||
set_camera_mode(m->area->camera, m->area->camera->defMode, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -3049,8 +3049,7 @@ static s32 check_for_instant_quicksand(struct MarioState *m) {
|
|||
}
|
||||
if (m->action == ACT_BUBBLED) { return FALSE; }
|
||||
|
||||
if (m->floor->type == SURFACE_INSTANT_QUICKSAND && m->action & ACT_FLAG_INVULNERABLE
|
||||
&& m->action != ACT_QUICKSAND_DEATH && m->action != ACT_SHOCKED) {
|
||||
if (m->floor && m->floor->type == SURFACE_INSTANT_QUICKSAND && m->action & ACT_FLAG_INVULNERABLE && m->action != ACT_QUICKSAND_DEATH && m->action != ACT_SHOCKED) {
|
||||
update_mario_sound_and_camera(m);
|
||||
return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0);
|
||||
}
|
||||
|
|
|
@ -696,6 +696,7 @@ void anim_and_audio_for_hold_walk(struct MarioState *m) {
|
|||
break;
|
||||
|
||||
default:
|
||||
val08 = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,6 +147,7 @@ void apply_water_current(struct MarioState *m, Vec3f step) {
|
|||
step[2] += currentSpeed * coss(currentAngle);
|
||||
}
|
||||
|
||||
if (!gCurrentArea) { return; }
|
||||
for (i = 0; i < 2; i++) {
|
||||
struct Whirlpool *whirlpool = gCurrentArea->whirlpools[i];
|
||||
if (whirlpool != NULL) {
|
||||
|
|
|
@ -72,14 +72,14 @@ static struct LuaObjectField sAreaFields[LUA_AREA_FIELD_COUNT] = {
|
|||
{ "nextSyncID", LVT_U32, offsetof(struct Area, nextSyncID), true, LOT_NONE },
|
||||
{ "numRedCoins", LVT_U8, offsetof(struct Area, numRedCoins), false, LOT_NONE },
|
||||
{ "numSecrets", LVT_U8, offsetof(struct Area, numSecrets), false, LOT_NONE },
|
||||
{ "objectSpawnInfos", LVT_COBJECT_P, offsetof(struct Area, objectSpawnInfos), false, LOT_SPAWNINFO },
|
||||
{ "paintingWarpNodes", LVT_COBJECT_P, offsetof(struct Area, paintingWarpNodes), false, LOT_WARPNODE },
|
||||
{ "objectSpawnInfos", LVT_COBJECT_P, offsetof(struct Area, objectSpawnInfos), true, LOT_SPAWNINFO },
|
||||
{ "paintingWarpNodes", LVT_COBJECT_P, offsetof(struct Area, paintingWarpNodes), true, LOT_WARPNODE },
|
||||
{ "surfaceRooms", LVT_S8_P, offsetof(struct Area, surfaceRooms), true, LOT_POINTER },
|
||||
{ "terrainData", LVT_S16_P, offsetof(struct Area, terrainData), true, LOT_POINTER },
|
||||
{ "terrainType", LVT_U16, offsetof(struct Area, terrainType), false, LOT_NONE },
|
||||
// { "unk04", LVT_COBJECT_P, offsetof(struct Area, unk04), true, LOT_??? }, <--- UNIMPLEMENTED
|
||||
// { "unused28", LVT_COBJECT_P, offsetof(struct Area, unused28), false, LOT_??? }, <--- UNIMPLEMENTED
|
||||
{ "warpNodes", LVT_COBJECT_P, offsetof(struct Area, warpNodes), false, LOT_OBJECTWARPNODE },
|
||||
{ "warpNodes", LVT_COBJECT_P, offsetof(struct Area, warpNodes), true, LOT_OBJECTWARPNODE },
|
||||
// { "whirlpools", LOT_???, offsetof(struct Area, whirlpools), false, LOT_??? }, <--- UNIMPLEMENTED
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue