diff --git a/build-windows-visual-studio/sm64ex.vcxproj b/build-windows-visual-studio/sm64ex.vcxproj
index 7864faca..3b2ac0e5 100644
--- a/build-windows-visual-studio/sm64ex.vcxproj
+++ b/build-windows-visual-studio/sm64ex.vcxproj
@@ -3968,10 +3968,15 @@
+
+
+
+
+
@@ -3979,6 +3984,7 @@
+
diff --git a/data/behavior_table.c b/data/behavior_table.c
index 2b1311f5..fbe918cd 100644
--- a/data/behavior_table.c
+++ b/data/behavior_table.c
@@ -529,20 +529,3 @@ const BehaviorScript* get_behavior_from_id(enum BehaviorId id) {
}
return gBehaviorTable[id];
}
-
-u8 is_behavior_a_coin(const BehaviorScript* behavior) {
- return behavior == bhvCoinFormationSpawn
- || behavior == bhvCoinFormation
- || behavior == bhvOneCoin
- || behavior == bhvYellowCoin
- || behavior == bhvTemporaryYellowCoin
- || behavior == bhvThreeCoinsSpawn
- || behavior == bhvTenCoinsSpawn
- || behavior == bhvHiddenBlueCoin
- || behavior == bhvMovingYellowCoin
- || behavior == bhvMovingBlueCoin
- || behavior == bhvBlueCoinSliding
- || behavior == bhvBlueCoinJumping
- || behavior == bhvRedCoin
- || behavior == bhvBowserCourseRedCoinStar;
-}
diff --git a/developer/network.sh b/developer/network.sh
index b274aefe..0d095ced 100644
--- a/developer/network.sh
+++ b/developer/network.sh
@@ -18,10 +18,10 @@ fi
#exit
# no debug, direct
-$FILE --server 27015 --configfile sm64config_server.txt &
-sleep 7
-$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt &
-exit
+#$FILE --server 27015 --configfile sm64config_server.txt &
+#sleep 7
+#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt &
+#exit
# debug on server
#$FILE --client 127.0.0.1 27015 --configfile sm64config_client.txt &
diff --git a/include/behavior_table.h b/include/behavior_table.h
index 0dc8fe7d..142df2f9 100644
--- a/include/behavior_table.h
+++ b/include/behavior_table.h
@@ -526,6 +526,5 @@ enum BehaviorId {
enum BehaviorId get_id_from_behavior(const BehaviorScript* behavior);
const BehaviorScript* get_behavior_from_id(enum BehaviorId id);
-u8 is_behavior_a_coin(const BehaviorScript* behavior);
#endif
diff --git a/include/macro_presets.h b/include/macro_presets.h
index a7ad50f6..861dfb49 100644
--- a/include/macro_presets.h
+++ b/include/macro_presets.h
@@ -12,373 +12,6 @@ struct MacroPreset
/*0x06*/ s16 param;
};
-struct MacroPreset MacroObjectPresets[] = {
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvOneCoin, MODEL_YELLOW_COIN, 0},
- {bhvMovingBlueCoin, MODEL_BLUE_COIN, 0},
- {bhvBlueCoinSliding, MODEL_BLUE_COIN, 0}, // unused
- {bhvRedCoin, MODEL_RED_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvCoinFormation, MODEL_NONE, 0},
- {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_RING},
- {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_ARROW},
- {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING},
- {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_VERTICAL},
- {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_RING},
- {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_RING | COIN_FORMATION_FLAG_VERTICAL},
- {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_ARROW}, // unused
- {bhvHiddenStarTrigger, MODEL_NONE, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvUnusedFakeStar, MODEL_STAR, 0}, // unused
- {bhvMessagePanel, MODEL_WOODEN_SIGNPOST, 0},
- {bhvCannonClosed, MODEL_DL_CANNON_LID, 0},
- {bhvBobombBuddyOpensCannon, MODEL_BOBOMB_BUDDY, 0},
- {bhvButterfly, MODEL_BUTTERFLY, 0}, // unused
- {bhvBouncingFireball, MODEL_NONE, 0}, // unused
- {bhvLargeFishGroup, MODEL_NONE, 0}, // unused
- {bhvLargeFishGroup, MODEL_NONE, 1},
- {bhvBetaFishSplashSpawner, MODEL_NONE, 0},
- {bhvHidden1upInPoleSpawner, MODEL_NONE, 0},
- {bhvGoomba, MODEL_GOOMBA, 1},
- {bhvGoomba, MODEL_GOOMBA, 2},
- {bhvGoombaTripletSpawner, MODEL_NONE, 0},
- {bhvGoombaTripletSpawner, MODEL_NONE, 8}, // unused
- {bhvSignOnWall, MODEL_NONE, 0},
- {bhvChuckya, MODEL_CHUCKYA, 0},
- {bhvCannon, MODEL_CANNON_BASE, 0},
- {bhvGoomba, MODEL_GOOMBA, 0},
- {bhvHomingAmp, MODEL_AMP, 0},
- {bhvCirclingAmp, MODEL_AMP, 0},
- {bhvCarrySomething1, MODEL_UNKNOWN_7D, 0}, // unused
- {bhvBetaTrampolineTop, MODEL_TRAMPOLINE, 0}, // unused
- {bhvFreeBowlingBall, MODEL_BOWLING_BALL, 0}, // unused
- {bhvSnufit, MODEL_SNUFIT, 0},
- {bhvRecoveryHeart, MODEL_HEART, 0},
- {bhv1upSliding, MODEL_1UP, 0},
- {bhv1Up, MODEL_1UP, 0},
- {bhv1upJumpOnApproach, MODEL_1UP, 0}, // unused
- {bhvHidden1up, MODEL_1UP, 0},
- {bhvHidden1upTrigger, MODEL_NONE, 0},
- {bhv1Up, MODEL_1UP, 1},
- {bhv1Up, MODEL_1UP, 2},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvBlueCoinSwitch, MODEL_BLUE_COIN_SWITCH, 0},
- {bhvHiddenBlueCoin, MODEL_BLUE_COIN, 0},
- {bhvCapSwitch, MODEL_CAP_SWITCH, 0}, // unused
- {bhvCapSwitch, MODEL_CAP_SWITCH, 1}, // unused
- {bhvCapSwitch, MODEL_CAP_SWITCH, 2}, // unused
- {bhvCapSwitch, MODEL_CAP_SWITCH, 3}, // unused
- {bhvWaterLevelDiamond, MODEL_BREAKABLE_BOX, 0}, // unused
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 0},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 1},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 2},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 3},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 4}, // unused
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 5},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 6},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 7},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 8},
- {bhvBreakableBox, MODEL_BREAKABLE_BOX, 0},
- {bhvBreakableBox, MODEL_BREAKABLE_BOX, 1},
- {bhvPushableMetalBox, MODEL_METAL_BOX, 0},
- {bhvBreakableBoxSmall, MODEL_BREAKABLE_BOX_SMALL, 0},
- {bhvFloorSwitchHiddenObjects, MODEL_PURPLE_SWITCH, 0},
- {bhvHiddenObject, MODEL_BREAKABLE_BOX, 0},
- {bhvHiddenObject, MODEL_BREAKABLE_BOX, 1}, // unused
- {bhvHiddenObject, MODEL_BREAKABLE_BOX, 2}, // unused
- {bhvBreakableBox, MODEL_BREAKABLE_BOX, 3},
- {bhvKoopaShellUnderwater, MODEL_KOOPA_SHELL, 0},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 9},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvBulletBill, MODEL_BULLET_BILL, 0}, // unused
- {bhvHeaveHo, MODEL_HEAVE_HO, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvThwomp2, MODEL_THWOMP, 0}, // unused
- {bhvFireSpitter, MODEL_BOWLING_BALL, 0},
- {bhvFlyGuy, MODEL_FLYGUY, 1},
- {bhvJumpingBox, MODEL_BREAKABLE_BOX, 0},
- {bhvTripletButterfly, MODEL_BUTTERFLY, 0},
- {bhvTripletButterfly, MODEL_BUTTERFLY, 4},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvSmallBully, MODEL_BULLY, 0},
- {bhvSmallBully, MODEL_BULLY_BOSS, 0}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvStub1D0C, MODEL_UNKNOWN_58, 0}, // unused
- {bhvBouncingFireball, MODEL_NONE, 0},
- {bhvFlamethrower, MODEL_NONE, 4},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvWoodenPost, MODEL_WOODEN_POST, 0},
- {bhvWaterBombSpawner, MODEL_NONE, 0},
- {bhvEnemyLakitu, MODEL_ENEMY_LAKITU, 0},
- {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 2}, // unused
- {bhvKoopaRaceEndpoint, MODEL_NONE, 0}, // unused
- {bhvBobomb, MODEL_BLACK_BOBOMB, 0},
- {bhvWaterBombCannon, MODEL_CANNON_BASE, 0}, // unused
- {bhvBobombBuddyOpensCannon, MODEL_BOBOMB_BUDDY, 0}, // unused
- {bhvWaterBombCannon, MODEL_CANNON_BASE, 0},
- {bhvBobomb, MODEL_BLACK_BOBOMB, 1},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvUnusedFakeStar, MODEL_UNKNOWN_54, 0}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvUnagi, MODEL_UNAGI, 0}, // unused
- {bhvSushiShark, MODEL_SUSHI, 0}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvStaticObject, MODEL_KLEPTO, 0}, // unused
- {bhvTweester, MODEL_TWEESTER, 0}, // unused
- {bhvPokey, MODEL_NONE, 0},
- {bhvPokey, MODEL_NONE, 0}, // unused
- {bhvToxBox, MODEL_SSL_TOX_BOX, 0}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvMontyMole, MODEL_MONTY_MOLE, 0}, // unused
- {bhvMontyMole, MODEL_MONTY_MOLE, 1},
- {bhvMontyMoleHole, MODEL_DL_MONTY_MOLE_HOLE, 0},
- {bhvFlyGuy, MODEL_FLYGUY, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvWigglerHead, MODEL_WIGGLER_HEAD, 0}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvSpindrift, MODEL_SPINDRIFT, 0},
- {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 0},
- {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 0}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvSmallPenguin, MODEL_PENGUIN, 0}, // unused
- {bhvTuxiesMother, MODEL_PENGUIN, 0}, // unused
- {bhvTuxiesMother, MODEL_PENGUIN, 0}, // unused
- {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 1}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0}, // unused
- {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0},
- {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0}, // unused
- {bhvGhostHuntBoo, MODEL_BOO, 0}, // unused
- {bhvGhostHuntBoo, MODEL_BOO, 0}, // unused
- {bhvCourtyardBooTriplet, MODEL_BOO, 0}, // unused
- {bhvBooWithCage, MODEL_BOO, 0}, // unused
- {bhvAlphaBooKey, MODEL_BETA_BOO_KEY, 0}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvChirpChirp, MODEL_NONE, 0},
- {bhvSeaweedBundle, MODEL_NONE, 0},
- {bhvBetaChestBottom, MODEL_TREASURE_CHEST_BASE, 0}, // unused
- {bhvBowserBomb, MODEL_WATER_MINE, 0}, // unused
- {bhvLargeFishGroup, MODEL_NONE, 2}, // unused
- {bhvLargeFishGroup, MODEL_NONE, 3},
- {bhvJetStreamRingSpawner, MODEL_WATER_RING, 0}, // unused
- {bhvJetStreamRingSpawner, MODEL_WATER_RING, 0}, // unused
- {bhvSkeeter, MODEL_SKEETER, 0},
- {bhvClamShell, MODEL_CLAM_SHELL, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvMacroUkiki, MODEL_UKIKI, 0}, // unused
- {bhvMacroUkiki, MODEL_UKIKI, 1}, // unused
- {bhvPiranhaPlant, MODEL_PIRANHA_PLANT, 0}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvSmallWhomp, MODEL_WHOMP, 0},
- {bhvChainChomp, MODEL_CHAIN_CHOMP, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 1},
- {bhvKoopa, MODEL_KOOPA_WITHOUT_SHELL, 0}, // unused
- {bhvWoodenPost, MODEL_WOODEN_POST, 0}, // unused
- {bhvFirePiranhaPlant, MODEL_PIRANHA_PLANT, 0},
- {bhvFirePiranhaPlant, MODEL_PIRANHA_PLANT, 1}, // unused
- {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 4},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvMoneybagHidden, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvSwoop, MODEL_SWOOP, 0},
- {bhvSwoop, MODEL_SWOOP, 1},
- {bhvMrI, MODEL_NONE, 0},
- {bhvScuttlebugSpawn, MODEL_NONE, 0},
- {bhvScuttlebug, MODEL_SCUTTLEBUG, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_UNKNOWN_54, 0}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvTTCRotatingSolid, MODEL_TTC_ROTATING_CUBE, 0},
- {bhvTTCRotatingSolid, MODEL_TTC_ROTATING_PRISM, 1},
- {bhvTTCPendulum, MODEL_TTC_PENDULUM, 0},
- {bhvTTCTreadmill, MODEL_TTC_LARGE_TREADMILL, 0},
- {bhvTTCTreadmill, MODEL_TTC_SMALL_TREADMILL, 1},
- {bhvTTCMovingBar, MODEL_TTC_PUSH_BLOCK, 0},
- {bhvTTCCog, MODEL_TTC_ROTATING_HEXAGON, 0},
- {bhvTTCCog, MODEL_TTC_ROTATING_TRIANGLE, 2},
- {bhvTTCPitBlock, MODEL_TTC_PIT_BLOCK, 0},
- {bhvTTCPitBlock, MODEL_TTC_PIT_BLOCK_UNUSED, 1}, // unused
- {bhvTTCElevator, MODEL_TTC_ELEVATOR_PLATFORM, 0},
- {bhvTTC2DRotator, MODEL_TTC_CLOCK_HAND, 0},
- {bhvTTCSpinner, MODEL_TTC_SPINNER, 0},
- {bhvTTC2DRotator, MODEL_TTC_SMALL_GEAR, 1},
- {bhvTTC2DRotator, MODEL_TTC_LARGE_GEAR, 1},
- {bhvTTCTreadmill, MODEL_TTC_LARGE_TREADMILL, 2},
- {bhvTTCTreadmill, MODEL_TTC_SMALL_TREADMILL, 3},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 10},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 11},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 12},
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 13}, // unused
- {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 14},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvSlidingPlatform2, MODEL_BITS_SLIDING_PLATFORM, 0}, // unused
- {bhvSlidingPlatform2, MODEL_BITS_TWIN_SLIDING_PLATFORMS, 0}, // unused
- {bhvAnotherTiltingPlatform, MODEL_BITDW_SLIDING_PLATFORM, 0}, // unused
- {bhvOctagonalPlatformRotating, MODEL_BITS_OCTAGONAL_PLATFORM, 0}, // unused
- {bhvAnimatesOnFloorSwitchPress, MODEL_BITS_STAIRCASE, 0}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvFerrisWheelAxle, MODEL_BITS_FERRIS_WHEEL_AXLE, 0}, // unused
- {bhvActivatedBackAndForthPlatform, MODEL_BITS_ARROW_PLATFORM, 0}, // unused
- {bhvSeesawPlatform, MODEL_BITS_SEESAW_PLATFORM, 0}, // unused
- {bhvSeesawPlatform, MODEL_BITS_TILTING_W_PLATFORM, 0}, // unused
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
- {bhvYellowCoin, MODEL_YELLOW_COIN, 0}
-};
+extern struct MacroPreset MacroObjectPresets[];
#endif // MACRO_PRESETS_H
diff --git a/include/object_fields.h b/include/object_fields.h
index 3b507da0..a6d771ce 100644
--- a/include/object_fields.h
+++ b/include/object_fields.h
@@ -406,7 +406,6 @@
#ifndef VERSION_JP
#define /*0x1B0*/ oCoinUnk1B0 OBJECT_FIELD_S32(0x4A)
#endif
-#define /*0x110*/ oCoinID OBJECT_FIELD_S16(0x49, 0)
/* Collision Particle */
#define /*0x0F4*/ oCollisionParticleUnkF4 OBJECT_FIELD_F32(0x1B)
diff --git a/src/game/behaviors/bobomb.inc.c b/src/game/behaviors/bobomb.inc.c
index f519f2a8..0eb3944e 100644
--- a/src/game/behaviors/bobomb.inc.c
+++ b/src/game/behaviors/bobomb.inc.c
@@ -39,7 +39,7 @@ void bobomb_act_explode(void) {
explosion->oGraphYOffset += 100.0f;
bobomb_spawn_coin();
- create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000, o->oSyncID);
+ create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000);
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
}
}
@@ -130,12 +130,12 @@ void generic_bobomb_free_loop(void) {
case BOBOMB_ACT_LAVA_DEATH:
if (obj_lava_death() == 1)
- create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000, o->oSyncID);
+ create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000);
break;
case BOBOMB_ACT_DEATH_PLANE_DEATH:
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
- create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000, o->oSyncID);
+ create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000);
break;
}
@@ -157,12 +157,12 @@ void stationary_bobomb_free_loop(void) {
case BOBOMB_ACT_LAVA_DEATH:
if (obj_lava_death() == 1)
- create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000, o->oSyncID);
+ create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000);
break;
case BOBOMB_ACT_DEATH_PLANE_DEATH:
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
- create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000, o->oSyncID);
+ create_respawner(MODEL_BLACK_BOBOMB, bhvBobomb, 3000);
break;
}
diff --git a/src/game/behaviors/breakable_box_small.inc.c b/src/game/behaviors/breakable_box_small.inc.c
index 7462f36d..327b2c9a 100644
--- a/src/game/behaviors/breakable_box_small.inc.c
+++ b/src/game/behaviors/breakable_box_small.inc.c
@@ -70,7 +70,7 @@ void breakable_box_small_released_loop(void) {
// Despawn, and create a corkbox respawner
if (o->oBreakableBoxSmallFramesSinceReleased > 900) {
- create_respawner(MODEL_BREAKABLE_BOX_SMALL, bhvBreakableBoxSmall, 3000, o->oSyncID);
+ create_respawner(MODEL_BREAKABLE_BOX_SMALL, bhvBreakableBoxSmall, 3000);
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
}
}
@@ -87,7 +87,7 @@ void breakable_box_small_idle_loop(void) {
case 101:
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
- create_respawner(MODEL_BREAKABLE_BOX_SMALL, bhvBreakableBoxSmall, 3000, o->oSyncID);
+ create_respawner(MODEL_BREAKABLE_BOX_SMALL, bhvBreakableBoxSmall, 3000);
break;
}
diff --git a/src/game/behaviors/corkbox.inc.c b/src/game/behaviors/corkbox.inc.c
index e19ba4f3..9db8c013 100644
--- a/src/game/behaviors/corkbox.inc.c
+++ b/src/game/behaviors/corkbox.inc.c
@@ -42,23 +42,30 @@ void bhv_respawner_loop(void) {
struct Object *spawnedObject;
if (!is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, o->oRespawnerMinSpawnDist)) {
+ u32 syncID = o->oSyncID;
spawnedObject = spawn_object(o, o->oRespawnerModelToRespawn, o->oRespawnerBehaviorToRespawn);
spawnedObject->oBehParams = o->oBehParams;
- spawnedObject->oSyncID = o->oSyncID;
+ spawnedObject->oSyncID = syncID;
+ network_override_object(syncID, spawnedObject);
+ o->oSyncID = 0;
+
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
}
}
-void create_respawner(s32 model, const BehaviorScript *behToSpawn, s32 minSpawnDist, u32 syncID) {
+void create_respawner(s32 model, const BehaviorScript *behToSpawn, s32 minSpawnDist) {
struct Object *respawner = spawn_object_abs_with_rot(o, 0, MODEL_NONE, bhvRespawner, o->oHomeX,
o->oHomeY, o->oHomeZ, 0, 0, 0);
+ u8 syncID = o->oSyncID;
respawner->oBehParams = o->oBehParams;
respawner->oRespawnerModelToRespawn = model;
respawner->oRespawnerMinSpawnDist = minSpawnDist;
respawner->oRespawnerBehaviorToRespawn = behToSpawn;
respawner->oSyncID = syncID;
- network_forget_sync_object(&gSyncObjects[syncID]);
- network_init_object(respawner, SYNC_DISTANCE_ONLY_EVENTS);
- o->oSyncID = 0;
+ if (gSyncObjects[syncID].staticLevelSpawn) {
+ network_override_object(syncID, respawner);
+ o->oSyncID = 0;
+ o->oFlags |= OBJ_FLAG_PERSISTENT_RESPAWN; // pretty sure this is required
+ }
}
diff --git a/src/game/behaviors/snowman.inc.c b/src/game/behaviors/snowman.inc.c
index ae08b065..6ec9b522 100644
--- a/src/game/behaviors/snowman.inc.c
+++ b/src/game/behaviors/snowman.inc.c
@@ -103,7 +103,7 @@ void snowmans_bottom_act_2(void) {
}
if (o->oTimer == 200) {
- create_respawner(MODEL_CCM_SNOWMAN_BASE, bhvSnowmansBottom, 3000, o->oSyncID);
+ create_respawner(MODEL_CCM_SNOWMAN_BASE, bhvSnowmansBottom, 3000);
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
}
}
diff --git a/src/game/behaviors/yoshi.inc.c b/src/game/behaviors/yoshi.inc.c
index 438a5646..b2b60d9f 100644
--- a/src/game/behaviors/yoshi.inc.c
+++ b/src/game/behaviors/yoshi.inc.c
@@ -47,7 +47,7 @@ void yoshi_walk_loop(void) {
o->oAction = YOSHI_ACT_TALK;
if (o->oPosY < 2100.0f) {
- create_respawner(MODEL_YOSHI, bhvYoshi, 3000, o->oSyncID);
+ create_respawner(MODEL_YOSHI, bhvYoshi, 3000);
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
}
}
diff --git a/src/game/interaction.c b/src/game/interaction.c
index 2ed9e9be..5e1499c3 100644
--- a/src/game/interaction.c
+++ b/src/game/interaction.c
@@ -838,9 +838,6 @@ u32 interact_coin(struct MarioState *m, UNUSED u32 interactType, struct Object *
}
network_send_collect_coin(o);
- if (o->oCoinID > 0) {
- coin_collection_remember(o->oCoinID);
- }
return FALSE;
}
diff --git a/src/game/macro_presets.c b/src/game/macro_presets.c
new file mode 100644
index 00000000..d498cbb6
--- /dev/null
+++ b/src/game/macro_presets.c
@@ -0,0 +1,370 @@
+#include "macro_presets.h"
+
+struct MacroPreset MacroObjectPresets[] = {
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvOneCoin, MODEL_YELLOW_COIN, 0},
+ {bhvMovingBlueCoin, MODEL_BLUE_COIN, 0},
+ {bhvBlueCoinSliding, MODEL_BLUE_COIN, 0}, // unused
+ {bhvRedCoin, MODEL_RED_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvCoinFormation, MODEL_NONE, 0},
+ {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_RING},
+ {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_ARROW},
+ {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING},
+ {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_VERTICAL},
+ {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_RING},
+ {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_RING | COIN_FORMATION_FLAG_VERTICAL},
+ {bhvCoinFormation, MODEL_NONE, COIN_FORMATION_FLAG_FLYING | COIN_FORMATION_FLAG_ARROW}, // unused
+ {bhvHiddenStarTrigger, MODEL_NONE, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvUnusedFakeStar, MODEL_STAR, 0}, // unused
+ {bhvMessagePanel, MODEL_WOODEN_SIGNPOST, 0},
+ {bhvCannonClosed, MODEL_DL_CANNON_LID, 0},
+ {bhvBobombBuddyOpensCannon, MODEL_BOBOMB_BUDDY, 0},
+ {bhvButterfly, MODEL_BUTTERFLY, 0}, // unused
+ {bhvBouncingFireball, MODEL_NONE, 0}, // unused
+ {bhvLargeFishGroup, MODEL_NONE, 0}, // unused
+ {bhvLargeFishGroup, MODEL_NONE, 1},
+ {bhvBetaFishSplashSpawner, MODEL_NONE, 0},
+ {bhvHidden1upInPoleSpawner, MODEL_NONE, 0},
+ {bhvGoomba, MODEL_GOOMBA, 1},
+ {bhvGoomba, MODEL_GOOMBA, 2},
+ {bhvGoombaTripletSpawner, MODEL_NONE, 0},
+ {bhvGoombaTripletSpawner, MODEL_NONE, 8}, // unused
+ {bhvSignOnWall, MODEL_NONE, 0},
+ {bhvChuckya, MODEL_CHUCKYA, 0},
+ {bhvCannon, MODEL_CANNON_BASE, 0},
+ {bhvGoomba, MODEL_GOOMBA, 0},
+ {bhvHomingAmp, MODEL_AMP, 0},
+ {bhvCirclingAmp, MODEL_AMP, 0},
+ {bhvCarrySomething1, MODEL_UNKNOWN_7D, 0}, // unused
+ {bhvBetaTrampolineTop, MODEL_TRAMPOLINE, 0}, // unused
+ {bhvFreeBowlingBall, MODEL_BOWLING_BALL, 0}, // unused
+ {bhvSnufit, MODEL_SNUFIT, 0},
+ {bhvRecoveryHeart, MODEL_HEART, 0},
+ {bhv1upSliding, MODEL_1UP, 0},
+ {bhv1Up, MODEL_1UP, 0},
+ {bhv1upJumpOnApproach, MODEL_1UP, 0}, // unused
+ {bhvHidden1up, MODEL_1UP, 0},
+ {bhvHidden1upTrigger, MODEL_NONE, 0},
+ {bhv1Up, MODEL_1UP, 1},
+ {bhv1Up, MODEL_1UP, 2},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvBlueCoinSwitch, MODEL_BLUE_COIN_SWITCH, 0},
+ {bhvHiddenBlueCoin, MODEL_BLUE_COIN, 0},
+ {bhvCapSwitch, MODEL_CAP_SWITCH, 0}, // unused
+ {bhvCapSwitch, MODEL_CAP_SWITCH, 1}, // unused
+ {bhvCapSwitch, MODEL_CAP_SWITCH, 2}, // unused
+ {bhvCapSwitch, MODEL_CAP_SWITCH, 3}, // unused
+ {bhvWaterLevelDiamond, MODEL_BREAKABLE_BOX, 0}, // unused
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 0},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 1},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 2},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 3},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 4}, // unused
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 5},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 6},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 7},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 8},
+ {bhvBreakableBox, MODEL_BREAKABLE_BOX, 0},
+ {bhvBreakableBox, MODEL_BREAKABLE_BOX, 1},
+ {bhvPushableMetalBox, MODEL_METAL_BOX, 0},
+ {bhvBreakableBoxSmall, MODEL_BREAKABLE_BOX_SMALL, 0},
+ {bhvFloorSwitchHiddenObjects, MODEL_PURPLE_SWITCH, 0},
+ {bhvHiddenObject, MODEL_BREAKABLE_BOX, 0},
+ {bhvHiddenObject, MODEL_BREAKABLE_BOX, 1}, // unused
+ {bhvHiddenObject, MODEL_BREAKABLE_BOX, 2}, // unused
+ {bhvBreakableBox, MODEL_BREAKABLE_BOX, 3},
+ {bhvKoopaShellUnderwater, MODEL_KOOPA_SHELL, 0},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 9},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvBulletBill, MODEL_BULLET_BILL, 0}, // unused
+ {bhvHeaveHo, MODEL_HEAVE_HO, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvThwomp2, MODEL_THWOMP, 0}, // unused
+ {bhvFireSpitter, MODEL_BOWLING_BALL, 0},
+ {bhvFlyGuy, MODEL_FLYGUY, 1},
+ {bhvJumpingBox, MODEL_BREAKABLE_BOX, 0},
+ {bhvTripletButterfly, MODEL_BUTTERFLY, 0},
+ {bhvTripletButterfly, MODEL_BUTTERFLY, 4},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvSmallBully, MODEL_BULLY, 0},
+ {bhvSmallBully, MODEL_BULLY_BOSS, 0}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvStub1D0C, MODEL_UNKNOWN_58, 0}, // unused
+ {bhvBouncingFireball, MODEL_NONE, 0},
+ {bhvFlamethrower, MODEL_NONE, 4},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvWoodenPost, MODEL_WOODEN_POST, 0},
+ {bhvWaterBombSpawner, MODEL_NONE, 0},
+ {bhvEnemyLakitu, MODEL_ENEMY_LAKITU, 0},
+ {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 2}, // unused
+ {bhvKoopaRaceEndpoint, MODEL_NONE, 0}, // unused
+ {bhvBobomb, MODEL_BLACK_BOBOMB, 0},
+ {bhvWaterBombCannon, MODEL_CANNON_BASE, 0}, // unused
+ {bhvBobombBuddyOpensCannon, MODEL_BOBOMB_BUDDY, 0}, // unused
+ {bhvWaterBombCannon, MODEL_CANNON_BASE, 0},
+ {bhvBobomb, MODEL_BLACK_BOBOMB, 1},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvUnusedFakeStar, MODEL_UNKNOWN_54, 0}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvUnagi, MODEL_UNAGI, 0}, // unused
+ {bhvSushiShark, MODEL_SUSHI, 0}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvStaticObject, MODEL_KLEPTO, 0}, // unused
+ {bhvTweester, MODEL_TWEESTER, 0}, // unused
+ {bhvPokey, MODEL_NONE, 0},
+ {bhvPokey, MODEL_NONE, 0}, // unused
+ {bhvToxBox, MODEL_SSL_TOX_BOX, 0}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvMontyMole, MODEL_MONTY_MOLE, 0}, // unused
+ {bhvMontyMole, MODEL_MONTY_MOLE, 1},
+ {bhvMontyMoleHole, MODEL_DL_MONTY_MOLE_HOLE, 0},
+ {bhvFlyGuy, MODEL_FLYGUY, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvWigglerHead, MODEL_WIGGLER_HEAD, 0}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvSpindrift, MODEL_SPINDRIFT, 0},
+ {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 0},
+ {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 0}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvSmallPenguin, MODEL_PENGUIN, 0}, // unused
+ {bhvTuxiesMother, MODEL_PENGUIN, 0}, // unused
+ {bhvTuxiesMother, MODEL_PENGUIN, 0}, // unused
+ {bhvMrBlizzard, MODEL_MR_BLIZZARD_HIDDEN, 1}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0}, // unused
+ {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0},
+ {bhvHauntedChair, MODEL_HAUNTED_CHAIR, 0}, // unused
+ {bhvGhostHuntBoo, MODEL_BOO, 0}, // unused
+ {bhvGhostHuntBoo, MODEL_BOO, 0}, // unused
+ {bhvCourtyardBooTriplet, MODEL_BOO, 0}, // unused
+ {bhvBooWithCage, MODEL_BOO, 0}, // unused
+ {bhvAlphaBooKey, MODEL_BETA_BOO_KEY, 0}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvChirpChirp, MODEL_NONE, 0},
+ {bhvSeaweedBundle, MODEL_NONE, 0},
+ {bhvBetaChestBottom, MODEL_TREASURE_CHEST_BASE, 0}, // unused
+ {bhvBowserBomb, MODEL_WATER_MINE, 0}, // unused
+ {bhvLargeFishGroup, MODEL_NONE, 2}, // unused
+ {bhvLargeFishGroup, MODEL_NONE, 3},
+ {bhvJetStreamRingSpawner, MODEL_WATER_RING, 0}, // unused
+ {bhvJetStreamRingSpawner, MODEL_WATER_RING, 0}, // unused
+ {bhvSkeeter, MODEL_SKEETER, 0},
+ {bhvClamShell, MODEL_CLAM_SHELL, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvMacroUkiki, MODEL_UKIKI, 0}, // unused
+ {bhvMacroUkiki, MODEL_UKIKI, 1}, // unused
+ {bhvPiranhaPlant, MODEL_PIRANHA_PLANT, 0}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvSmallWhomp, MODEL_WHOMP, 0},
+ {bhvChainChomp, MODEL_CHAIN_CHOMP, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 1},
+ {bhvKoopa, MODEL_KOOPA_WITHOUT_SHELL, 0}, // unused
+ {bhvWoodenPost, MODEL_WOODEN_POST, 0}, // unused
+ {bhvFirePiranhaPlant, MODEL_PIRANHA_PLANT, 0},
+ {bhvFirePiranhaPlant, MODEL_PIRANHA_PLANT, 1}, // unused
+ {bhvKoopa, MODEL_KOOPA_WITH_SHELL, 4},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvMoneybagHidden, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvSwoop, MODEL_SWOOP, 0},
+ {bhvSwoop, MODEL_SWOOP, 1},
+ {bhvMrI, MODEL_NONE, 0},
+ {bhvScuttlebugSpawn, MODEL_NONE, 0},
+ {bhvScuttlebug, MODEL_SCUTTLEBUG, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_UNKNOWN_54, 0}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvTTCRotatingSolid, MODEL_TTC_ROTATING_CUBE, 0},
+ {bhvTTCRotatingSolid, MODEL_TTC_ROTATING_PRISM, 1},
+ {bhvTTCPendulum, MODEL_TTC_PENDULUM, 0},
+ {bhvTTCTreadmill, MODEL_TTC_LARGE_TREADMILL, 0},
+ {bhvTTCTreadmill, MODEL_TTC_SMALL_TREADMILL, 1},
+ {bhvTTCMovingBar, MODEL_TTC_PUSH_BLOCK, 0},
+ {bhvTTCCog, MODEL_TTC_ROTATING_HEXAGON, 0},
+ {bhvTTCCog, MODEL_TTC_ROTATING_TRIANGLE, 2},
+ {bhvTTCPitBlock, MODEL_TTC_PIT_BLOCK, 0},
+ {bhvTTCPitBlock, MODEL_TTC_PIT_BLOCK_UNUSED, 1}, // unused
+ {bhvTTCElevator, MODEL_TTC_ELEVATOR_PLATFORM, 0},
+ {bhvTTC2DRotator, MODEL_TTC_CLOCK_HAND, 0},
+ {bhvTTCSpinner, MODEL_TTC_SPINNER, 0},
+ {bhvTTC2DRotator, MODEL_TTC_SMALL_GEAR, 1},
+ {bhvTTC2DRotator, MODEL_TTC_LARGE_GEAR, 1},
+ {bhvTTCTreadmill, MODEL_TTC_LARGE_TREADMILL, 2},
+ {bhvTTCTreadmill, MODEL_TTC_SMALL_TREADMILL, 3},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 10},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 11},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 12},
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 13}, // unused
+ {bhvExclamationBox, MODEL_EXCLAMATION_BOX, 14},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvSlidingPlatform2, MODEL_BITS_SLIDING_PLATFORM, 0}, // unused
+ {bhvSlidingPlatform2, MODEL_BITS_TWIN_SLIDING_PLATFORMS, 0}, // unused
+ {bhvAnotherTiltingPlatform, MODEL_BITDW_SLIDING_PLATFORM, 0}, // unused
+ {bhvOctagonalPlatformRotating, MODEL_BITS_OCTAGONAL_PLATFORM, 0}, // unused
+ {bhvAnimatesOnFloorSwitchPress, MODEL_BITS_STAIRCASE, 0}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvFerrisWheelAxle, MODEL_BITS_FERRIS_WHEEL_AXLE, 0}, // unused
+ {bhvActivatedBackAndForthPlatform, MODEL_BITS_ARROW_PLATFORM, 0}, // unused
+ {bhvSeesawPlatform, MODEL_BITS_SEESAW_PLATFORM, 0}, // unused
+ {bhvSeesawPlatform, MODEL_BITS_TILTING_W_PLATFORM, 0}, // unused
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0},
+ {bhvYellowCoin, MODEL_YELLOW_COIN, 0}
+};
diff --git a/src/game/obj_behaviors.h b/src/game/obj_behaviors.h
index 8b5fbea7..35355f12 100644
--- a/src/game/obj_behaviors.h
+++ b/src/game/obj_behaviors.h
@@ -87,7 +87,7 @@ void bhv_bobomb_bully_death_smoke_init(void);
void bhv_bobomb_explosion_bubble_init(void);
void bhv_bobomb_explosion_bubble_loop(void);
void bhv_respawner_loop(void);
-void create_respawner(s32 arg0, const BehaviorScript *behToSpawn, s32 minSpawnDist, u32 syncID);
+void create_respawner(s32 arg0, const BehaviorScript *behToSpawn, s32 minSpawnDist);
void bhv_small_bully_init(void);
void bhv_big_bully_init(void);
void bully_check_mario_collision(void);
diff --git a/src/pc/controller/controller_keyboard_debug.c b/src/pc/controller/controller_keyboard_debug.c
index ed99ae47..573a9bb5 100644
--- a/src/pc/controller/controller_keyboard_debug.c
+++ b/src/pc/controller/controller_keyboard_debug.c
@@ -7,7 +7,7 @@
#ifdef DEBUG
-static u8 warpToLevel = LEVEL_BOB;
+static u8 warpToLevel = LEVEL_CCM;
#define SCANCODE_0 0x0B
#define SCANCODE_1 0x02
diff --git a/src/pc/network/network.c b/src/pc/network/network.c
index ae8d3542..7ff16cd9 100644
--- a/src/pc/network/network.c
+++ b/src/pc/network/network.c
@@ -100,15 +100,6 @@ void network_on_loaded_level(void) {
gSyncObjects[i].staticLevelSpawn = true;
}
- // give all coins an ID
- u8 coinId = 0;
- for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) {
- struct Object* o = &gObjectPool[i];
- if (o->activeFlags & ACTIVE_FLAG_DEACTIVATED) { continue; }
- if (!is_behavior_a_coin(o->behavior)) { continue; }
- o->oCoinID = ++coinId;
- }
-
// check for level change
struct NetworkPlayer* np = gNetworkPlayerLocal;
if (np != NULL) {
diff --git a/src/pc/network/network_player.c b/src/pc/network/network_player.c
index 6cdf8d75..cf7a016d 100644
--- a/src/pc/network/network_player.c
+++ b/src/pc/network/network_player.c
@@ -33,6 +33,20 @@ struct NetworkPlayer* network_player_from_global_index(u8 globalIndex) {
return NULL;
}
+struct NetworkPlayer* get_network_player_from_valid_location(s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex) {
+ for (int i = 0; i < MAX_PLAYERS; i++) {
+ struct NetworkPlayer* np = &gNetworkPlayers[i];
+ if (!np->connected) { continue; }
+ if (!np->currAreaSyncValid) { continue; }
+ if (np->currCourseNum != courseNum) { continue; }
+ if (np->currActNum != actNum) { continue; }
+ if (np->currLevelNum != levelNum) { continue; }
+ if (np->currAreaIndex != areaIndex) { continue; }
+ return np;
+ }
+ return NULL;
+}
+
void network_player_update(void) {
float elapsed = (clock() - gLastNetworkSend) / (float)CLOCKS_PER_SEC;
if (elapsed > NETWORK_PLAYER_TIMEOUT / 3.0f) {
diff --git a/src/pc/network/network_player.h b/src/pc/network/network_player.h
index dd91d2fd..95078746 100644
--- a/src/pc/network/network_player.h
+++ b/src/pc/network/network_player.h
@@ -41,6 +41,7 @@ extern struct NetworkPlayer* gNetworkPlayerServer;
bool network_player_any_connected(void);
u8 network_player_connected_count(void);
struct NetworkPlayer* network_player_from_global_index(u8 globalIndex);
+struct NetworkPlayer* get_network_player_from_valid_location(s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex);
void network_player_update(void);
u8 network_player_connected(enum NetworkPlayerType type, u8 globalIndex);
u8 network_player_disconnected(u8 globalIndex);
diff --git a/src/pc/network/packets/packet.c b/src/pc/network/packets/packet.c
index 8e4c4e6c..6e227b51 100644
--- a/src/pc/network/packets/packet.c
+++ b/src/pc/network/packets/packet.c
@@ -62,8 +62,10 @@ void packet_receive(struct Packet* p) {
case PACKET_LEVEL_AREA: network_receive_level_area(p); break;
case PACKET_LEVEL_AREA_VALID: network_receive_level_area_valid(p); break;
case PACKET_LOCATION_REQUEST: network_receive_location_request(p); break;
- case PACKET_CLIENT_LOCATION_REQUEST: network_receive_client_location_request(p); break;
+ case PACKET_LOCATION_REQUEST_CLIENT: network_receive_location_request_client(p); break;
case PACKET_LOCATION_RESPONSE: network_receive_location_response(p); break;
+ case PACKET_MACRO_DELETIONS: network_receive_macro_deletions(p); break;
+ case PACKET_SPAWN_INFO_DELETIONS: network_receive_spawn_info_deletions(p); break;
///
case PACKET_CUSTOM: network_receive_custom(p); break;
default: LOG_ERROR("received unknown packet: %d", p->buffer[0]);
diff --git a/src/pc/network/packets/packet.h b/src/pc/network/packets/packet.h
index 53f427d9..255bb492 100644
--- a/src/pc/network/packets/packet.h
+++ b/src/pc/network/packets/packet.h
@@ -34,8 +34,10 @@ enum PacketType {
PACKET_LEVEL_AREA,
PACKET_LEVEL_AREA_VALID,
PACKET_LOCATION_REQUEST,
- PACKET_CLIENT_LOCATION_REQUEST,
+ PACKET_LOCATION_REQUEST_CLIENT,
PACKET_LOCATION_RESPONSE,
+ PACKET_MACRO_DELETIONS,
+ PACKET_SPAWN_INFO_DELETIONS,
///
PACKET_CUSTOM = 255,
};
@@ -87,6 +89,7 @@ void network_receive_player(struct Packet* p);
// packet_object.c
struct Packet* get_last_sync_ent_reliable_packet(u8 syncId);
void forget_ent_reliable_packet(struct Object* o);
+void network_override_object(u8 syncId, struct Object* o);
struct SyncObject* network_init_object(struct Object* object, float maxSyncDistance);
void network_init_object_field(struct Object* o, void* field);
bool network_owns_object(struct Object* o);
@@ -174,15 +177,23 @@ void network_send_level_area_valid(u8 toGlobalIndex);
void network_receive_level_area_valid(struct Packet* p);
// packet_location_request.c
-void coin_collection_remember(u8 coinId);
-void coin_collection_clear(void);
-void static_spawn_removal_remember(u8 syncId);
-void static_spawn_removal_clear(void);
void network_send_location_request(void);
void network_receive_location_request(struct Packet* p);
-void network_send_client_location_request(u8 destGlobalIndex, u8 srcGlobalIndex);
-void network_receive_client_location_request(struct Packet* p);
+
+// packet_location_request_client.c
+void network_send_location_request_client(u8 destGlobalIndex, u8 srcGlobalIndex);
+void network_receive_location_request_client(struct Packet* p);
+
+// packet_location_response.c
void network_send_location_response(u8 destGlobalIndex);
void network_receive_location_response(struct Packet* p);
+// packet_macro_deletions.c
+void network_send_macro_deletions(u8 destGlobalIndex);
+void network_receive_macro_deletions(struct Packet* p);
+
+// packet_spawn_info_deletions.c
+void network_send_spawn_info_deletions(u8 destGlobalIndex);
+void network_receive_spawn_info_deletions(struct Packet* p);
+
#endif
diff --git a/src/pc/network/packets/packet_location_request.c b/src/pc/network/packets/packet_location_request.c
index 6bcd6e74..08f022e3 100644
--- a/src/pc/network/packets/packet_location_request.c
+++ b/src/pc/network/packets/packet_location_request.c
@@ -1,62 +1,10 @@
#include
#include "../network.h"
-#include "menu/custom_menu_system.h"
-#include "game/interaction.h"
-#include "game/object_list_processor.h"
-#include "game/object_helpers.h"
-#include "game/interaction.h"
-#include "game/level_update.h"
-#include "object_constants.h"
-#include "object_fields.h"
-#include "behavior_table.h"
-#include "model_ids.h"
//#define DISABLE_MODULE_LOG 1
#include "pc/debuglog.h"
extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
-#define MAX_STATIC_SPAWN_REMOVAL 256
-u8 sStaticSpawnRemoval[MAX_STATIC_SPAWN_REMOVAL] = { 0 };
-u8 sStaticSpawnRemovalIndex = 0;
-
-#define MAX_COIN_COLLECTION 128
-u8 sCoinCollection[MAX_STATIC_SPAWN_REMOVAL] = { 0 };
-u8 sCoinCollectionIndex = 0;
-
-void coin_collection_remember(u8 coinId) {
- sCoinCollection[sCoinCollectionIndex++] = coinId;
- if (sStaticSpawnRemovalIndex >= MAX_COIN_COLLECTION) { sStaticSpawnRemovalIndex = MAX_COIN_COLLECTION - 1; }
-}
-
-void coin_collection_clear(void) {
- sCoinCollectionIndex = 0;
-}
-
-void static_spawn_removal_remember(u8 syncId) {
- sStaticSpawnRemoval[sStaticSpawnRemovalIndex++] = syncId;
- if (sStaticSpawnRemovalIndex == 0) { sStaticSpawnRemovalIndex = MAX_STATIC_SPAWN_REMOVAL - 1; }
-}
-
-void static_spawn_removal_clear(void) {
- sStaticSpawnRemovalIndex = 0;
-}
-
-struct NetworkPlayer* get_network_player_from_valid_location(s16 courseNum, s16 actNum, s16 levelNum, s16 areaIndex) {
- for (int i = 0; i < MAX_PLAYERS; i++) {
- struct NetworkPlayer* np = &gNetworkPlayers[i];
- if (!np->connected) { continue; }
- if (!np->currAreaSyncValid) { continue; }
- if (np->currCourseNum != courseNum) { continue; }
- if (np->currActNum != actNum) { continue; }
- if (np->currLevelNum != levelNum) { continue; }
- if (np->currAreaIndex != areaIndex) { continue; }
- return np;
- }
- return NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
void network_send_location_request(void) {
if (gNetworkType == NT_SERVER) {
struct NetworkPlayer* np = get_network_player_from_valid_location(gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex);
@@ -64,7 +12,7 @@ void network_send_location_request(void) {
gNetworkPlayerLocal->currAreaSyncValid = true;
return;
}
- network_send_client_location_request(gNetworkPlayerLocal->globalIndex, np->globalIndex);
+ network_send_location_request_client(gNetworkPlayerLocal->globalIndex, np->globalIndex);
return;
}
@@ -107,263 +55,6 @@ void network_receive_location_request(struct Packet* p) {
} else if (np2 == gNetworkPlayerLocal) {
network_send_location_response(np->globalIndex);
} else {
- network_send_client_location_request(np->globalIndex, np2->globalIndex);
+ network_send_location_request_client(np->globalIndex, np2->globalIndex);
}
}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void network_send_client_location_request(u8 destGlobalIndex, u8 srcGlobalIndex) {
- if (gNetworkType != NT_SERVER) {
- LOG_ERROR("client can't send a 'client location request'");
- return;
- }
-
- struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
- if (destNp == NULL || !destNp->connected) {
- LOG_ERROR("network_send_client_location_request: dest np is invalid (global %d)", destGlobalIndex);
- return;
- }
-
- struct Packet p;
- packet_init(&p, PACKET_CLIENT_LOCATION_REQUEST, true, false);
- packet_write(&p, &destGlobalIndex, sizeof(u8));
- packet_write(&p, &destNp->currCourseNum, sizeof(s16));
- packet_write(&p, &destNp->currActNum, sizeof(s16));
- packet_write(&p, &destNp->currLevelNum, sizeof(s16));
- packet_write(&p, &destNp->currAreaIndex, sizeof(s16));
-
- struct NetworkPlayer* srcNp = network_player_from_global_index(srcGlobalIndex);
- if (srcNp == NULL || !srcNp->connected || !srcNp->currAreaSyncValid) {
- LOG_ERROR("network_send_client_location_request: source np is invalid (global %d)", srcGlobalIndex);
- return;
- }
-
- network_send_to(srcNp->localIndex, &p);
-}
-
-void network_receive_client_location_request(struct Packet* p) {
- if (gNetworkType == NT_SERVER) {
- LOG_ERROR("server is receiving a 'client location request'!");
- return;
- }
-
- u8 destGlobalIndex;
- s16 courseNum, actNum, levelNum, areaIndex;
- packet_read(p, &destGlobalIndex, sizeof(u8));
- packet_read(p, &courseNum, sizeof(s16));
- packet_read(p, &actNum, sizeof(s16));
- packet_read(p, &levelNum, sizeof(s16));
- packet_read(p, &areaIndex, sizeof(s16));
-
- if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
- LOG_ERROR("Receiving 'client location request' with the wrong location!");
- return;
- }
-
- network_send_location_response(destGlobalIndex);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void network_send_location_response(u8 destGlobalIndex) {
- if (!gNetworkPlayerLocal->currAreaSyncValid) {
- LOG_ERROR("my area is invalid");
- return;
- }
-
- struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
- if (destNp == NULL || !destNp->connected) {
- LOG_ERROR("network_send_location_response: dest np is invalid");
- return;
- }
-
- struct Packet p;
- packet_init(&p, PACKET_LOCATION_RESPONSE, true, false);
- packet_write(&p, &gCurrCourseNum, sizeof(s16));
- packet_write(&p, &gCurrActNum, sizeof(s16));
- packet_write(&p, &gCurrLevelNum, sizeof(s16));
- packet_write(&p, &gCurrAreaIndex, sizeof(s16));
-
- // level variables
- packet_write(&p, &gMarioStates[0].numCoins, sizeof(s16));
- packet_write(&p, &gPssSlideStarted, sizeof(u8));
- packet_write(&p, &gHudDisplay.timer, sizeof(u16));
-
- // static spawn removal
- packet_write(&p, &sStaticSpawnRemovalIndex, sizeof(u8));
- for (int i = 0; i < sStaticSpawnRemovalIndex; i++) {
- packet_write(&p, &sStaticSpawnRemoval[i], sizeof(u8));
- }
-
- // coin collection
- packet_write(&p, &sCoinCollectionIndex, sizeof(u8));
- for (int i = 0; i < sCoinCollectionIndex; i++) {
- packet_write(&p, &sCoinCollection[i], sizeof(u8));
- }
-
- // respawners
- u8 respawnerCount = 0;
- for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
- struct SyncObject* so = &gSyncObjects[i];
- if (so == NULL || so->o == NULL || so->behavior != bhvRespawner) { continue; }
- respawnerCount++;
- }
-
- packet_write(&p, &respawnerCount, sizeof(u8));
- for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
- struct SyncObject* so = &gSyncObjects[i];
- if (so == NULL || so->o == NULL || so->behavior != bhvRespawner) { continue; }
- u32 behaviorToRespawn = get_id_from_behavior(so->o->oRespawnerBehaviorToRespawn);
- packet_write(&p, &so->o->oPosX, sizeof(f32));
- packet_write(&p, &so->o->oPosY, sizeof(f32));
- packet_write(&p, &so->o->oPosZ, sizeof(f32));
- packet_write(&p, &so->o->oBehParams, sizeof(s32));
- packet_write(&p, &so->o->oRespawnerModelToRespawn, sizeof(s32));
- packet_write(&p, &so->o->oRespawnerMinSpawnDist, sizeof(f32));
- packet_write(&p, &behaviorToRespawn, sizeof(s32));
- packet_write(&p, &so->o->oSyncID, sizeof(u32));
- }
-
- network_send_to(destNp->localIndex, &p);
-
- // send non-static objects
- for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
- struct SyncObject* so = &gSyncObjects[i];
- if (so == NULL || so->o == NULL || so->o->oSyncID != i) { continue; }
- if (so->staticLevelSpawn) { continue; }
- if (so->o->behavior == bhvRespawner) { continue; }
- struct Object* spawn_objects[] = { so->o };
-
- // TODO: move find model to a utility file/function
- // find model
- u32 model = 0;
- for (int j = 0; j < 256; j++) {
- if (so->o->header.gfx.sharedChild == gLoadedGraphNodes[j]) {
- model = j;
- break;
- }
- }
-
- u32 models[] = { model };
- network_send_spawn_objects_to(destNp->localIndex, spawn_objects, models, 1);
- }
-
- // send last reliable ent packet
- for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
- struct SyncObject* so = &gSyncObjects[i];
- if (so == NULL || so->o == NULL) { continue; }
- struct Packet* entPacket = get_last_sync_ent_reliable_packet(i);
- if (entPacket->error) { continue; }
- struct Packet p2 = { 0 };
- packet_duplicate(entPacket, &p2);
- network_send_to(destNp->localIndex, &p2);
- }
-}
-
-void network_receive_location_response(struct Packet* p) {
- s16 courseNum, actNum, levelNum, areaIndex;
- packet_read(p, &courseNum, sizeof(s16));
- packet_read(p, &actNum, sizeof(s16));
- packet_read(p, &levelNum, sizeof(s16));
- packet_read(p, &areaIndex, sizeof(s16));
-
- if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
- LOG_ERROR("Receiving 'location response' with the wrong location!");
- return;
- }
-
- if (gNetworkPlayerLocal->currAreaSyncValid) {
- LOG_ERROR("Receiving 'location response' when our location is already valid!");
- return;
- }
-
- s16 numCoins;
- packet_read(p, &numCoins, sizeof(s16));
-
- u8 pssSlideStarted;
- u16 hudDisplayTimer;
- packet_read(p, &pssSlideStarted, sizeof(u8));
- packet_read(p, &hudDisplayTimer, sizeof(u16));
- if (pssSlideStarted) {
- level_control_timer(TIMER_CONTROL_SHOW);
- level_control_timer(TIMER_CONTROL_START);
- gPssSlideStarted = TRUE;
- gHudDisplay.timer = hudDisplayTimer;
- }
-
- u8 staticSpawnRemovals;
- static_spawn_removal_clear();
-
- // read static spawn removals
- packet_read(p, &staticSpawnRemovals, sizeof(u8));
- for (int i = 0; i < staticSpawnRemovals; i++) {
- u8 syncId;
- packet_read(p, &syncId, sizeof(u8));
- struct SyncObject* so = &gSyncObjects[syncId];
- if (so != NULL) {
- if (so->o != NULL) {
- obj_mark_for_deletion(so->o);
- }
- network_forget_sync_object(so);
- }
- }
-
- // read coin collections
- packet_read(p, &sCoinCollectionIndex, sizeof(u8));
- for (int i = 0; i < sCoinCollectionIndex; i++) {
- packet_read(p, &sCoinCollection[i], sizeof(u8));
- }
-
- // collect the coins
- for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) {
- struct Object* o = &gObjectPool[i];
- if (o->activeFlags & ACTIVE_FLAG_DEACTIVATED) { continue; }
- if (!is_behavior_a_coin(o->behavior)) { continue; }
- for (int j = 0; j < sCoinCollectionIndex; j++) {
- if (o->oCoinID == sCoinCollection[j]) {
- o->oInteractStatus = INT_STATUS_INTERACTED;
- }
- }
- }
-
- // read respawners
- u8 respawnerCount = 0;
- packet_read(p, &respawnerCount, sizeof(u8));
-
- for (int i = 0; i < respawnerCount; i++) {
- f32 posX, posY, posZ;
- packet_read(p, &posX, sizeof(f32));
- packet_read(p, &posY, sizeof(f32));
- packet_read(p, &posZ, sizeof(f32));
-
- s32 behParams, respawnerModelToRespawn;
- packet_read(p, &behParams, sizeof(s32));
- packet_read(p, &respawnerModelToRespawn, sizeof(s32));
-
- f32 respawnerMinSpawnDist;
- packet_read(p, &respawnerMinSpawnDist, sizeof(f32));
-
- u32 behaviorToRespawn, syncId;
- packet_read(p, &behaviorToRespawn, sizeof(u32));
- packet_read(p, &syncId, sizeof(u32));
-
- struct Object* respawner = spawn_object_abs_with_rot(gMarioStates[0].marioObj, 0, MODEL_NONE, bhvRespawner, posX, posY, posZ, 0, 0, 0);
- respawner->parentObj = respawner;
- respawner->oBehParams = behParams;
- respawner->oRespawnerModelToRespawn = respawnerModelToRespawn;
- respawner->oRespawnerMinSpawnDist = respawnerMinSpawnDist;
- respawner->oRespawnerBehaviorToRespawn = get_behavior_from_id(behaviorToRespawn);
- respawner->oSyncID = syncId;
-
- network_forget_sync_object(&gSyncObjects[syncId]);
- network_init_object(respawner, SYNC_DISTANCE_ONLY_EVENTS);
- }
-
- gMarioStates[0].numCoins = numCoins;
- gNetworkPlayerLocal->currAreaSyncValid = true;
-
- if (gNetworkType != NT_SERVER) {
- network_send_level_area_valid(0);
- }
-}
\ No newline at end of file
diff --git a/src/pc/network/packets/packet_location_request_client.c b/src/pc/network/packets/packet_location_request_client.c
new file mode 100644
index 00000000..3bb59d69
--- /dev/null
+++ b/src/pc/network/packets/packet_location_request_client.c
@@ -0,0 +1,57 @@
+#include
+#include "../network.h"
+//#define DISABLE_MODULE_LOG 1
+#include "pc/debuglog.h"
+
+extern s16 gCurrCourseNum, gCurrActNum, gCurrLevelNum, gCurrAreaIndex;
+
+void network_send_location_request_client(u8 destGlobalIndex, u8 srcGlobalIndex) {
+ if (gNetworkType != NT_SERVER) {
+ LOG_ERROR("client can't send a 'client location request'");
+ return;
+ }
+
+ struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
+ if (destNp == NULL || !destNp->connected) {
+ LOG_ERROR("network_send_client_location_request: dest np is invalid (global %d)", destGlobalIndex);
+ return;
+ }
+
+ struct Packet p;
+ packet_init(&p, PACKET_LOCATION_REQUEST_CLIENT, true, false);
+ packet_write(&p, &destGlobalIndex, sizeof(u8));
+ packet_write(&p, &destNp->currCourseNum, sizeof(s16));
+ packet_write(&p, &destNp->currActNum, sizeof(s16));
+ packet_write(&p, &destNp->currLevelNum, sizeof(s16));
+ packet_write(&p, &destNp->currAreaIndex, sizeof(s16));
+
+ struct NetworkPlayer* srcNp = network_player_from_global_index(srcGlobalIndex);
+ if (srcNp == NULL || !srcNp->connected || !srcNp->currAreaSyncValid) {
+ LOG_ERROR("network_send_client_location_request: source np is invalid (global %d)", srcGlobalIndex);
+ return;
+ }
+
+ network_send_to(srcNp->localIndex, &p);
+}
+
+void network_receive_location_request_client(struct Packet* p) {
+ if (gNetworkType == NT_SERVER) {
+ LOG_ERROR("server is receiving a 'client location request'!");
+ return;
+ }
+
+ u8 destGlobalIndex;
+ s16 courseNum, actNum, levelNum, areaIndex;
+ packet_read(p, &destGlobalIndex, sizeof(u8));
+ packet_read(p, &courseNum, sizeof(s16));
+ packet_read(p, &actNum, sizeof(s16));
+ packet_read(p, &levelNum, sizeof(s16));
+ packet_read(p, &areaIndex, sizeof(s16));
+
+ if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
+ LOG_ERROR("Receiving 'client location request' with the wrong location!");
+ return;
+ }
+
+ network_send_location_response(destGlobalIndex);
+}
diff --git a/src/pc/network/packets/packet_location_response.c b/src/pc/network/packets/packet_location_response.c
new file mode 100644
index 00000000..0bb6f0cd
--- /dev/null
+++ b/src/pc/network/packets/packet_location_response.c
@@ -0,0 +1,189 @@
+#include
+#include "../network.h"
+#include "game/interaction.h"
+#include "game/object_list_processor.h"
+#include "game/object_helpers.h"
+#include "game/interaction.h"
+#include "game/level_update.h"
+#include "game/macro_special_objects.h"
+#include "object_constants.h"
+#include "object_fields.h"
+#include "behavior_table.h"
+#include "model_ids.h"
+//#define DISABLE_MODULE_LOG 1
+#include "pc/debuglog.h"
+
+void network_send_location_response(u8 destGlobalIndex) {
+ if (!gNetworkPlayerLocal->currAreaSyncValid) {
+ LOG_ERROR("my area is invalid");
+ return;
+ }
+
+ struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
+ if (destNp == NULL || !destNp->connected) {
+ LOG_ERROR("network_send_location_response: dest np is invalid");
+ return;
+ }
+
+ struct Packet p;
+ packet_init(&p, PACKET_LOCATION_RESPONSE, true, false);
+ packet_write(&p, &gCurrCourseNum, sizeof(s16));
+ packet_write(&p, &gCurrActNum, sizeof(s16));
+ packet_write(&p, &gCurrLevelNum, sizeof(s16));
+ packet_write(&p, &gCurrAreaIndex, sizeof(s16));
+
+ // level variables
+ packet_write(&p, &gMarioStates[0].numCoins, sizeof(s16));
+ packet_write(&p, &gPssSlideStarted, sizeof(u8));
+ packet_write(&p, &gHudDisplay.timer, sizeof(u16));
+
+ // respawners
+ u8 respawnerCount = 0;
+ for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
+ struct SyncObject* so = &gSyncObjects[i];
+ if (so == NULL || so->o == NULL || so->o->behavior != bhvRespawner) { continue; }
+ respawnerCount++;
+ }
+
+ packet_write(&p, &respawnerCount, sizeof(u8));
+ for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
+ struct SyncObject* so = &gSyncObjects[i];
+ if (so == NULL || so->o == NULL || so->o->behavior != bhvRespawner) { continue; }
+ u32 behaviorToRespawn = get_id_from_behavior(so->o->oRespawnerBehaviorToRespawn);
+ packet_write(&p, &so->o->oPosX, sizeof(f32));
+ packet_write(&p, &so->o->oPosY, sizeof(f32));
+ packet_write(&p, &so->o->oPosZ, sizeof(f32));
+ packet_write(&p, &so->o->oBehParams, sizeof(s32));
+ packet_write(&p, &so->o->oRespawnerModelToRespawn, sizeof(s32));
+ packet_write(&p, &so->o->oRespawnerMinSpawnDist, sizeof(f32));
+ packet_write(&p, &behaviorToRespawn, sizeof(s32));
+ packet_write(&p, &so->o->oSyncID, sizeof(u32));
+ LOG_INFO("tx respawner");
+ }
+
+ network_send_to(destNp->localIndex, &p);
+
+ // send macro deletions
+ network_send_macro_deletions(destGlobalIndex);
+
+ // send spawn info
+ network_send_spawn_info_deletions(destGlobalIndex);
+
+ // send non-static objects
+ for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
+ struct SyncObject* so = &gSyncObjects[i];
+ if (so == NULL || so->o == NULL || so->o->oSyncID != i) { continue; }
+ if (so->staticLevelSpawn) { continue; }
+ if (so->o->behavior == bhvRespawner) { continue; }
+ struct Object* spawn_objects[] = { so->o };
+
+ // TODO: move find model to a utility file/function
+ // find model
+ u32 model = 0;
+ for (int j = 0; j < 256; j++) {
+ if (so->o->header.gfx.sharedChild == gLoadedGraphNodes[j]) {
+ model = j;
+ break;
+ }
+ }
+
+ u32 models[] = { model };
+ network_send_spawn_objects_to(destNp->localIndex, spawn_objects, models, 1);
+ LOG_INFO("tx non-static");
+ }
+
+ // send last reliable ent packet
+ for (int i = 0; i < MAX_SYNC_OBJECTS; i++) {
+ struct SyncObject* so = &gSyncObjects[i];
+ if (so == NULL || so->o == NULL) { continue; }
+ struct Packet* entPacket = get_last_sync_ent_reliable_packet(i);
+ if (entPacket->error) { continue; }
+ struct Packet p2 = { 0 };
+ packet_duplicate(entPacket, &p2);
+ network_send_to(destNp->localIndex, &p2);
+ }
+
+ LOG_INFO("tx location response");
+}
+
+void network_receive_location_response(struct Packet* p) {
+ s16 courseNum, actNum, levelNum, areaIndex;
+ packet_read(p, &courseNum, sizeof(s16));
+ packet_read(p, &actNum, sizeof(s16));
+ packet_read(p, &levelNum, sizeof(s16));
+ packet_read(p, &areaIndex, sizeof(s16));
+
+ if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum || areaIndex != gCurrAreaIndex) {
+ LOG_ERROR("Receiving 'location response' with the wrong location!");
+ return;
+ }
+
+ if (gNetworkPlayerLocal->currAreaSyncValid) {
+ LOG_ERROR("Receiving 'location response' when our location is already valid!");
+ return;
+ }
+
+ s16 numCoins;
+ packet_read(p, &numCoins, sizeof(s16));
+
+ u8 pssSlideStarted;
+ u16 hudDisplayTimer;
+ packet_read(p, &pssSlideStarted, sizeof(u8));
+ packet_read(p, &hudDisplayTimer, sizeof(u16));
+ if (pssSlideStarted) {
+ level_control_timer(TIMER_CONTROL_SHOW);
+ level_control_timer(TIMER_CONTROL_START);
+ gPssSlideStarted = TRUE;
+ gHudDisplay.timer = hudDisplayTimer;
+ }
+
+ // read respawners
+ u8 respawnerCount = 0;
+ packet_read(p, &respawnerCount, sizeof(u8));
+
+ for (int i = 0; i < respawnerCount; i++) {
+ f32 posX, posY, posZ;
+ packet_read(p, &posX, sizeof(f32));
+ packet_read(p, &posY, sizeof(f32));
+ packet_read(p, &posZ, sizeof(f32));
+
+ s32 behParams, respawnerModelToRespawn;
+ packet_read(p, &behParams, sizeof(s32));
+ packet_read(p, &respawnerModelToRespawn, sizeof(s32));
+
+ f32 respawnerMinSpawnDist;
+ packet_read(p, &respawnerMinSpawnDist, sizeof(f32));
+
+ u32 behaviorToRespawn, syncId;
+ packet_read(p, &behaviorToRespawn, sizeof(u32));
+ packet_read(p, &syncId, sizeof(u32));
+
+ struct SyncObject* so = &gSyncObjects[syncId];
+
+ LOG_INFO("rx respawner");
+ if (so->staticLevelSpawn) {
+ struct Object* respawner = spawn_object_abs_with_rot(gMarioStates[0].marioObj, 0, MODEL_NONE, bhvRespawner, posX, posY, posZ, 0, 0, 0);
+ respawner->parentObj = respawner;
+ respawner->oBehParams = behParams;
+ respawner->oRespawnerModelToRespawn = respawnerModelToRespawn;
+ respawner->oRespawnerMinSpawnDist = respawnerMinSpawnDist;
+ respawner->oRespawnerBehaviorToRespawn = get_behavior_from_id(behaviorToRespawn);
+ respawner->oSyncID = syncId;
+
+ struct Object* o = so->o;
+ o->oSyncID = 0;
+ o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
+
+ so->o = respawner;
+ LOG_INFO("rx respawner replaced!");
+ }
+ }
+
+ gMarioStates[0].numCoins = numCoins;
+ gNetworkPlayerLocal->currAreaSyncValid = true;
+
+ if (gNetworkType != NT_SERVER) {
+ network_send_level_area_valid(0);
+ }
+ LOG_INFO("rx location response");
+}
\ No newline at end of file
diff --git a/src/pc/network/packets/packet_macro_deletions.c b/src/pc/network/packets/packet_macro_deletions.c
new file mode 100644
index 00000000..54a02899
--- /dev/null
+++ b/src/pc/network/packets/packet_macro_deletions.c
@@ -0,0 +1,205 @@
+#include
+#include "../network.h"
+#include "game/interaction.h"
+#include "game/object_list_processor.h"
+#include "game/object_helpers.h"
+#include "game/interaction.h"
+#include "game/level_update.h"
+#include "game/macro_special_objects.h"
+#include "macro_presets.h"
+#include "object_constants.h"
+#include "object_fields.h"
+#include "behavior_table.h"
+#include "model_ids.h"
+#define DISABLE_MODULE_LOG 1
+#include "pc/debuglog.h"
+
+static struct Object* get_object_matching_respawn_info(s16* respawnInfo) {
+ for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) {
+ struct Object* o = &gObjectPool[i];
+ if (o->respawnInfo == respawnInfo) { return o; }
+ }
+
+ return NULL;
+}
+
+////
+
+void network_send_macro_deletions_area(u8 destGlobalIndex, u8 areaIndex) {
+ // check that the area is active
+ struct Area* area = &gAreaData[areaIndex];
+ if (area->unk04 == NULL) { return; }
+
+ struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
+ if (destNp == NULL || !destNp->connected) {
+ LOG_ERROR("network_send_macro_deletions_area: dest np is invalid");
+ return;
+ }
+
+ // write header
+ struct Packet p;
+ packet_init(&p, PACKET_MACRO_DELETIONS, true, false);
+ packet_write(&p, &gCurrCourseNum, sizeof(s16));
+ packet_write(&p, &gCurrActNum, sizeof(s16));
+ packet_write(&p, &gCurrLevelNum, sizeof(s16));
+ packet_write(&p, &gCurrAreaIndex, sizeof(s16));
+
+ // write this area's index
+ packet_write(&p, &areaIndex, sizeof(u8));
+
+ // write the amount of deletions
+ u8 zero = 0;
+ u8* macroDeletionCount = &p.buffer[p.cursor];
+ packet_write(&p, &zero, sizeof(u8));
+
+ // loop through macro objects for deletions
+ s16* macroObjList = area->macroObjects;
+ while (*macroObjList != -1) {
+ // grab preset ID
+ s32 presetID = (*macroObjList & 0x1FF) - 31; // Preset identifier for MacroObjectPresets array
+ if (presetID < 0) { break; }
+
+ // parse respawn info
+ macroObjList += 4;
+ s16* respawnInfo = macroObjList++;
+
+ // if a macro object was destroyed, send its respawnInfo offset
+ if (((*respawnInfo >> 8) & RESPAWN_INFO_DONT_RESPAWN) == RESPAWN_INFO_DONT_RESPAWN) {
+ *macroDeletionCount = *macroDeletionCount + 1;
+ u16 offset = respawnInfo - area->macroObjects;
+ packet_write(&p, &offset, sizeof(u16));
+ LOG_INFO("tx macro deletion: offset %d", offset);
+ }
+ }
+
+ // write the amount of special cases
+ u8* macroSpecialCount = &p.buffer[p.cursor];
+ packet_write(&p, &zero, sizeof(u8));
+
+ // loop through macro objects for special cases
+ macroObjList = area->macroObjects;
+ while (*macroObjList != -1) {
+ // grab preset ID
+ s32 presetID = (*macroObjList & 0x1FF) - 31; // Preset identifier for MacroObjectPresets array
+ if (presetID < 0) { break; }
+
+ // parse respawn info
+ macroObjList += 4;
+ s16* respawnInfo = macroObjList++;
+
+ // check for special cases
+ const BehaviorScript* behavior = MacroObjectPresets[presetID].behavior;
+ if (behavior == bhvCoinFormation && *respawnInfo != 0) {
+ *macroSpecialCount = *macroSpecialCount + 1;
+ u16 offset = respawnInfo - area->macroObjects;
+ packet_write(&p, &offset, sizeof(u16));
+ packet_write(&p, respawnInfo, sizeof(s16));
+ LOG_INFO("tx macro special: offset %d, respawnInfo %d", offset, *respawnInfo);
+ }
+ }
+
+ // send the packet if there are deletions
+ if (*macroDeletionCount > 0 || *macroSpecialCount > 0) {
+ network_send_to(destNp->localIndex, &p);
+ LOG_INFO("tx macro deletion for area %d (count %d)", areaIndex, *macroDeletionCount);
+ }
+}
+
+void network_send_macro_deletions(u8 destGlobalIndex) {
+ if (!gNetworkPlayerLocal->currAreaSyncValid) {
+ LOG_ERROR("my area is invalid");
+ return;
+ }
+
+ struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
+ if (destNp == NULL || !destNp->connected) {
+ LOG_ERROR("network_send_macro_deletions: dest np is invalid");
+ return;
+ }
+
+ for (int i = 0; i < 8; i++) {
+ network_send_macro_deletions_area(destGlobalIndex, i);
+ }
+}
+
+void network_receive_macro_deletions(struct Packet* p) {
+ s16 courseNum, actNum, levelNum, areaIndex;
+ packet_read(p, &courseNum, sizeof(s16));
+ packet_read(p, &actNum, sizeof(s16));
+ packet_read(p, &levelNum, sizeof(s16));
+ packet_read(p, &areaIndex, sizeof(s16));
+
+ if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum) {
+ LOG_ERROR("Receiving 'location response' with the wrong location!");
+ return;
+ }
+
+ u8 thisAreaIndex;
+ packet_read(p, &thisAreaIndex, sizeof(u8));
+
+ // read and execute macro deletions
+ u8 macroDeletionCount;
+ packet_read(p, ¯oDeletionCount, sizeof(u8));
+ LOG_INFO("rx macro deletions (count %d)", macroDeletionCount);
+
+ while (macroDeletionCount-- > 0) {
+ u16 offset;
+ packet_read(p, &offset, sizeof(u16));
+ LOG_INFO("rx macro deletion: offset %d", offset);
+
+ // mark respawninfo as dont respawn
+ s16* respawnInfo = gAreaData[thisAreaIndex].macroObjects + offset;
+ *respawnInfo |= RESPAWN_INFO_DONT_RESPAWN << 8;
+
+ struct Object* o = get_object_matching_respawn_info(respawnInfo);
+ if (o != NULL) {
+ obj_mark_for_deletion(o);
+ LOG_INFO("rx macro deletion: object");
+ if (o->oSyncID != 0) {
+ struct SyncObject* so = &gSyncObjects[o->oSyncID];
+ if (so->o == o) {
+ network_forget_sync_object(so);
+ LOG_INFO("rx macro deletion: sync object");
+ }
+ }
+ }
+ }
+
+ // read and execute macro specials
+
+ u8 macroSpecialCount;
+ packet_read(p, ¯oSpecialCount, sizeof(u8));
+ while (macroSpecialCount-- > 0) {
+ u16 offset;
+ packet_read(p, &offset, sizeof(u16));
+
+ s16* respawnInfo = gAreaData[thisAreaIndex].macroObjects + offset;
+ packet_read(p, respawnInfo, sizeof(s16));
+ LOG_INFO("rx macro special: offset %d, respawnInfo %d", offset, *respawnInfo);
+
+ s32 presetID = (*(respawnInfo - 4) & 0x1FF) - 31;
+ const BehaviorScript* behavior = MacroObjectPresets[presetID].behavior;
+
+ struct Object* o = get_object_matching_respawn_info(respawnInfo);
+ if (o != NULL) {
+ LOG_INFO("rx macro special: object");
+ // coin formation
+ if (behavior == bhvCoinFormation) {
+ o->oBehParams = *respawnInfo;
+ o->oCoinUnkF4 = (o->oBehParams >> 8) & 0xFF;
+
+ u8 childIndex = 0;
+ for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) {
+ struct Object* o2 = &gObjectPool[i];
+ if (o2->parentObj != o) { continue; }
+ if (o2 == o) { continue; }
+ if (o2->behavior != bhvCoinFormationSpawn && o2->behavior != bhvYellowCoin) { continue; }
+ if (o->oCoinUnkF4 & (1 << childIndex++)) {
+ obj_mark_for_deletion(o2);
+ }
+ }
+ LOG_INFO("rx macro special: coin formation");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/pc/network/packets/packet_object.c b/src/pc/network/packets/packet_object.c
index ad5a366e..881bfc0e 100644
--- a/src/pc/network/packets/packet_object.c
+++ b/src/pc/network/packets/packet_object.c
@@ -63,7 +63,14 @@ static bool should_own_object(struct SyncObject* so) {
return true;
}
+void network_override_object(u8 syncId, struct Object* o) {
+ gSyncObjects[syncId].o = o;
+}
+
struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance) {
+ // HACK: an odd way to detect if this entity was spawned from a staticLevel respawner
+ bool wasStaticRespawner = (o->oSyncID != 0 && gSyncObjects[o->oSyncID].o == o && gSyncObjects[o->oSyncID].staticLevelSpawn);
+
// generate new sync ID
network_set_sync_id(o);
@@ -90,7 +97,7 @@ struct SyncObject* network_init_object(struct Object *o, float maxSyncDistance)
so->override_ownership = NULL;
so->syncDeathEvent = true;
so->randomSeed = (u16)(o->oSyncID * 7951);
- so->staticLevelSpawn = false;
+ so->staticLevelSpawn = wasStaticRespawner;
memset(so->extraFields, 0, sizeof(void*) * MAX_SYNC_OBJECT_FIELDS);
sLastSyncEntReliablePacket[o->oSyncID].error = true;
@@ -137,8 +144,6 @@ void network_clear_sync_objects(void) {
network_forget_sync_object(&gSyncObjects[i]);
}
nextSyncID = 1;
- static_spawn_removal_clear();
- coin_collection_clear();
}
void network_set_sync_id(struct Object* o) {
@@ -372,6 +377,8 @@ static void packet_read_object_only_death(struct Packet* p, struct Object* o) {
void network_send_object(struct Object* o) {
// sanity check SyncObject
if (!network_sync_object_initialized(o)) { return; }
+ if (o->behavior == bhvRespawner) { return; }
+
struct SyncObject* so = &gSyncObjects[o->oSyncID];
if (so == NULL) { return; }
if (o != so->o) {
@@ -493,20 +500,19 @@ void network_receive_object(struct Packet* p) {
}
void network_forget_sync_object(struct SyncObject* so) {
+ // invalidate last packet sent
if (so->staticLevelSpawn && so->o != NULL) {
u8 syncId = so->o->oSyncID;
struct SyncObject* so2 = &gSyncObjects[syncId];
if (so == so2) {
- static_spawn_removal_remember(syncId);
sLastSyncEntReliablePacket[syncId].error = true;
}
}
+
so->o = NULL;
so->behavior = NULL;
so->reserved = 0;
so->owned = false;
- so->staticLevelSpawn = false;
-
}
void network_update_objects(void) {
diff --git a/src/pc/network/packets/packet_spawn_info_deletions.c b/src/pc/network/packets/packet_spawn_info_deletions.c
new file mode 100644
index 00000000..38400754
--- /dev/null
+++ b/src/pc/network/packets/packet_spawn_info_deletions.c
@@ -0,0 +1,140 @@
+#include
+#include "../network.h"
+#include "game/interaction.h"
+#include "game/object_list_processor.h"
+#include "game/object_helpers.h"
+#include "game/interaction.h"
+#include "game/level_update.h"
+#include "game/macro_special_objects.h"
+#include "object_constants.h"
+#include "object_fields.h"
+#include "behavior_table.h"
+#include "model_ids.h"
+#define DISABLE_MODULE_LOG 1
+#include "pc/debuglog.h"
+
+static struct Object* get_object_matching_respawn_info(s32* respawnInfo) {
+ for (int i = 0; i < OBJECT_POOL_CAPACITY; i++) {
+ struct Object* o = &gObjectPool[i];
+ if (o->respawnInfo == respawnInfo) { return o; }
+ }
+
+ return NULL;
+}
+
+////
+
+void network_send_spawn_info_deletions_area(u8 destGlobalIndex, u8 areaIndex) {
+ // check that the area is active
+ struct Area* area = &gAreaData[areaIndex];
+ if (area->unk04 == NULL) { return; }
+
+ struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
+ if (destNp == NULL || !destNp->connected) {
+ LOG_ERROR("network_send_spawn_info_deletions_area: dest np is invalid");
+ return;
+ }
+
+ // write header
+ struct Packet p;
+ packet_init(&p, PACKET_SPAWN_INFO_DELETIONS, true, false);
+ packet_write(&p, &gCurrCourseNum, sizeof(s16));
+ packet_write(&p, &gCurrActNum, sizeof(s16));
+ packet_write(&p, &gCurrLevelNum, sizeof(s16));
+ packet_write(&p, &gCurrAreaIndex, sizeof(s16));
+
+ // write this area's index
+ packet_write(&p, &areaIndex, sizeof(u8));
+
+ // write the amount of deletions
+ u8 zero = 0;
+ u8* spawnInfoDeletionCount = &p.buffer[p.cursor];
+ packet_write(&p, &zero, sizeof(u8));
+
+ // loop through spawn infos
+ struct SpawnInfo* spawnInfo = area->objectSpawnInfos;
+ u16 spawnInfoIndex = 0;
+
+ while (spawnInfo != NULL) {
+ // if a spawn info object was destroyed, send its spawn info index
+ if (((spawnInfo->behaviorArg >> 8) & RESPAWN_INFO_DONT_RESPAWN) == RESPAWN_INFO_DONT_RESPAWN) {
+ *spawnInfoDeletionCount = *spawnInfoDeletionCount + 1;
+ packet_write(&p, &spawnInfoIndex, sizeof(u16));
+ LOG_INFO("tx spawn info deletion: index %d", spawnInfoIndex);
+ }
+
+ spawnInfo = spawnInfo->next;
+ spawnInfoIndex++;
+ }
+
+ // send the packet if there are deletions
+ if (*spawnInfoDeletionCount > 0) {
+ network_send_to(destNp->localIndex, &p);
+ LOG_INFO("tx spawn info deletion for area %d (count %d)", areaIndex, *spawnInfoDeletionCount);
+ }
+}
+
+void network_send_spawn_info_deletions(u8 destGlobalIndex) {
+ if (!gNetworkPlayerLocal->currAreaSyncValid) {
+ LOG_ERROR("my area is invalid");
+ return;
+ }
+
+ struct NetworkPlayer* destNp = network_player_from_global_index(destGlobalIndex);
+ if (destNp == NULL || !destNp->connected) {
+ LOG_ERROR("network_send_spawn_info_deletions: dest np is invalid");
+ return;
+ }
+
+ for (int i = 0; i < 8; i++) {
+ network_send_spawn_info_deletions_area(destGlobalIndex, i);
+ }
+}
+
+void network_receive_spawn_info_deletions(struct Packet* p) {
+ s16 courseNum, actNum, levelNum, areaIndex;
+ packet_read(p, &courseNum, sizeof(s16));
+ packet_read(p, &actNum, sizeof(s16));
+ packet_read(p, &levelNum, sizeof(s16));
+ packet_read(p, &areaIndex, sizeof(s16));
+
+ if (courseNum != gCurrCourseNum || actNum != gCurrActNum || levelNum != gCurrLevelNum) {
+ LOG_ERROR("Receiving 'location response' with the wrong location!");
+ return;
+ }
+
+ u8 thisAreaIndex, spawnInfoDeletionCount;
+ packet_read(p, &thisAreaIndex, sizeof(u8));
+ packet_read(p, &spawnInfoDeletionCount, sizeof(u8));
+ LOG_INFO("rx spawn info deletions (count %d)", spawnInfoDeletionCount);
+ if (spawnInfoDeletionCount <= 0) { return; }
+
+ struct SpawnInfo* spawnInfo = gAreaData[thisAreaIndex].objectSpawnInfos;
+ u16 spawnInfoIndex = 0;
+
+ u16 spawnInfoDeleteIndex;
+ packet_read(p, &spawnInfoDeleteIndex, sizeof(u16));
+
+ while (spawnInfo != NULL && spawnInfoDeletionCount > 0) {
+ if (spawnInfoIndex == spawnInfoDeleteIndex) {
+ u32* respawnInfo = &spawnInfo->behaviorArg;
+ struct Object* o = get_object_matching_respawn_info(respawnInfo);
+ if (o != NULL) {
+ obj_mark_for_deletion(o);
+ LOG_INFO("rx spawn info deletion: object");
+ if (o->oSyncID != 0) {
+ struct SyncObject* so = &gSyncObjects[o->oSyncID];
+ if (so->o == o) {
+ network_forget_sync_object(so);
+ LOG_INFO("rx spawn info deletion: sync object");
+ }
+ }
+ }
+ spawnInfoDeletionCount--;
+ packet_read(p, &spawnInfoDeleteIndex, sizeof(u16));
+ }
+
+ spawnInfo = spawnInfo->next;
+ spawnInfoIndex++;
+ }
+}
\ No newline at end of file