mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-04-26 03:51:46 +00:00
Add dynamic object limit
This commit is contained in:
parent
006fc1dcd2
commit
0f07bb9d2d
26 changed files with 260 additions and 71 deletions
|
|
@ -35,6 +35,7 @@ in_files = [
|
|||
"src/game/player_palette.h",
|
||||
"src/engine/graph_node.h",
|
||||
"include/PR/gbi.h",
|
||||
"src/game/object_list_processor.h",
|
||||
]
|
||||
|
||||
out_filename_c = 'src/pc/lua/smlua_cobject_autogen.c'
|
||||
|
|
|
|||
|
|
@ -6668,7 +6668,10 @@ TIME_STOP_MARIO_OPENED_DOOR = (1 << 5)
|
|||
TIME_STOP_ACTIVE = (1 << 6)
|
||||
|
||||
--- @type integer
|
||||
OBJECT_POOL_CAPACITY = 1200
|
||||
OBJECT_POOL_CAPACITY = 0xFFFFFFFF
|
||||
|
||||
--- @type integer
|
||||
OBJECT_POOL_NODE_CAPACITY = 256
|
||||
|
||||
OBJ_LIST_PLAYER = 0 --- @type ObjectList
|
||||
OBJ_LIST_EXT = 1 --- @type ObjectList
|
||||
|
|
|
|||
|
|
@ -12124,6 +12124,12 @@ function obj_anim_skip_interpolation(o)
|
|||
-- ...
|
||||
end
|
||||
|
||||
--- @return integer
|
||||
--- Gets the amount of objects in this area
|
||||
function obj_get_count()
|
||||
-- ...
|
||||
end
|
||||
|
||||
--- Resets every modified dialog back to vanilla
|
||||
function smlua_text_utils_reset_all()
|
||||
-- ...
|
||||
|
|
|
|||
|
|
@ -1282,6 +1282,11 @@
|
|||
--- @field public overridePaletteIndex integer
|
||||
--- @field public overridePaletteIndexLp integer
|
||||
|
||||
--- @class NumTimesCalled
|
||||
--- @field public floor integer
|
||||
--- @field public ceil integer
|
||||
--- @field public wall integer
|
||||
|
||||
--- @class Object
|
||||
--- @field public header ObjectNode
|
||||
--- @field public prevObj Object
|
||||
|
|
@ -2062,6 +2067,12 @@
|
|||
--- @field public gfx GraphNodeObject
|
||||
--- @field public next ObjectNode
|
||||
--- @field public prev ObjectNode
|
||||
--- @field public pool ObjectPoolNode
|
||||
|
||||
--- @class ObjectPoolNode
|
||||
--- @field public pool Object[]
|
||||
--- @field public freeList ObjectNode
|
||||
--- @field public next ObjectPoolNode
|
||||
|
||||
--- @class ObjectWarpNode
|
||||
--- @field public node WarpNode
|
||||
|
|
|
|||
|
|
@ -2907,6 +2907,7 @@
|
|||
- TIME_STOP_MARIO_OPENED_DOOR
|
||||
- TIME_STOP_ACTIVE
|
||||
- OBJECT_POOL_CAPACITY
|
||||
- OBJECT_POOL_NODE_CAPACITY
|
||||
|
||||
### [enum ObjectList](#ObjectList)
|
||||
| Identifier | Value |
|
||||
|
|
|
|||
|
|
@ -3622,6 +3622,27 @@ Skips animation interpolation for a frame
|
|||
|
||||
<br />
|
||||
|
||||
## [obj_get_count](#obj_get_count)
|
||||
|
||||
### Description
|
||||
Gets the amount of objects in this area
|
||||
|
||||
### Lua Example
|
||||
`local integerValue = obj_get_count()`
|
||||
|
||||
### Parameters
|
||||
- None
|
||||
|
||||
### Returns
|
||||
- `integer`
|
||||
|
||||
### C Prototype
|
||||
`u32 obj_get_count(void);`
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
---
|
||||
# functions from smlua_text_utils.h
|
||||
|
||||
|
|
|
|||
|
|
@ -2143,6 +2143,7 @@
|
|||
- [set_whirlpools](functions-7.md#set_whirlpools)
|
||||
- [obj_skip_interpolation](functions-7.md#obj_skip_interpolation)
|
||||
- [obj_anim_skip_interpolation](functions-7.md#obj_anim_skip_interpolation)
|
||||
- [obj_get_count](functions-7.md#obj_get_count)
|
||||
|
||||
<br />
|
||||
|
||||
|
|
|
|||
|
|
@ -66,9 +66,11 @@
|
|||
- [ModFsFile](#ModFsFile)
|
||||
- [NametagsSettings](#NametagsSettings)
|
||||
- [NetworkPlayer](#NetworkPlayer)
|
||||
- [NumTimesCalled](#NumTimesCalled)
|
||||
- [Object](#Object)
|
||||
- [ObjectHitbox](#ObjectHitbox)
|
||||
- [ObjectNode](#ObjectNode)
|
||||
- [ObjectPoolNode](#ObjectPoolNode)
|
||||
- [ObjectWarpNode](#ObjectWarpNode)
|
||||
- [Painting](#Painting)
|
||||
- [PaintingValues](#PaintingValues)
|
||||
|
|
@ -1869,6 +1871,18 @@
|
|||
|
||||
<br />
|
||||
|
||||
## [NumTimesCalled](#NumTimesCalled)
|
||||
|
||||
| Field | Type | Access |
|
||||
| ----- | ---- | ------ |
|
||||
| floor | `integer` | |
|
||||
| ceil | `integer` | |
|
||||
| wall | `integer` | |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [Object](#Object)
|
||||
|
||||
| Field | Type | Access |
|
||||
|
|
@ -2674,6 +2688,19 @@
|
|||
| gfx | [GraphNodeObject](structs.md#GraphNodeObject) | read-only |
|
||||
| next | [ObjectNode](structs.md#ObjectNode) | read-only |
|
||||
| prev | [ObjectNode](structs.md#ObjectNode) | read-only |
|
||||
| pool | [ObjectPoolNode](structs.md#ObjectPoolNode) | |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
<br />
|
||||
|
||||
## [ObjectPoolNode](#ObjectPoolNode)
|
||||
|
||||
| Field | Type | Access |
|
||||
| ----- | ---- | ------ |
|
||||
| pool | `Array` <`Object`> | read-only |
|
||||
| freeList | [ObjectNode](structs.md#ObjectNode) | read-only |
|
||||
| next | [ObjectPoolNode](structs.md#ObjectPoolNode) | |
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
||||
|
|
|
|||
|
|
@ -232,6 +232,7 @@ struct ObjectNode
|
|||
struct GraphNodeObject gfx;
|
||||
struct ObjectNode *next;
|
||||
struct ObjectNode *prev;
|
||||
struct ObjectPoolNode* pool;
|
||||
};
|
||||
|
||||
// NOTE: Since ObjectNode is the first member of Object, it is difficult to determine
|
||||
|
|
|
|||
|
|
@ -644,11 +644,11 @@ void clear_dynamic_surfaces(void) {
|
|||
|
||||
clear_spatial_partition(&gDynamicSurfacePartition[0][0]);
|
||||
|
||||
for (u16 i = 0; i < OBJECT_POOL_CAPACITY; i++) {
|
||||
struct Object *obj = &gObjectPool[i];
|
||||
traverse_object_pools(
|
||||
struct Object *obj = &node->pool[i];
|
||||
obj->firstSurface = 0;
|
||||
obj->numSurfaces = 0;
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,14 +12,16 @@ void bhv_object_bubble_loop(void) {
|
|||
f32 bubbleY = o->oPosY;
|
||||
|
||||
if (bubbleY > waterY) {
|
||||
if (gFreeObjectList.next) {
|
||||
bubbleSplash = spawn_object_at_origin(o, 0, MODEL_SMALL_WATER_SPLASH, bhvBubbleSplash);
|
||||
if (bubbleSplash != NULL) {
|
||||
bubbleSplash->oPosX = o->oPosX;
|
||||
bubbleSplash->oPosY = bubbleY + 5.0f;
|
||||
bubbleSplash->oPosZ = o->oPosZ;
|
||||
traverse_object_pools(
|
||||
if (node != NULL && node->freeList.next != NULL) {
|
||||
bubbleSplash = spawn_object_at_origin(o, 0, MODEL_SMALL_WATER_SPLASH, bhvBubbleSplash);
|
||||
if (bubbleSplash != NULL) {
|
||||
bubbleSplash->oPosX = o->oPosX;
|
||||
bubbleSplash->oPosY = bubbleY + 5.0f;
|
||||
bubbleSplash->oPosZ = o->oPosZ;
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ void bhv_tree_snow_or_leaf_loop(void) {
|
|||
obj_mark_for_deletion(o);
|
||||
if (o->oTimer > 100)
|
||||
obj_mark_for_deletion(o);
|
||||
if (gPrevFrameObjectCount > (OBJECT_POOL_CAPACITY * 212 / 240))
|
||||
obj_mark_for_deletion(o);
|
||||
//if (gPrevFrameObjectCount > (OBJECT_POOL_CAPACITY * 212 / 240))
|
||||
// obj_mark_for_deletion(o);
|
||||
o->oFaceAnglePitch += o->oAngleVelPitch;
|
||||
o->oFaceAngleRoll += o->oAngleVelRoll;
|
||||
o->oVelY += -3.0f;
|
||||
|
|
|
|||
|
|
@ -63,8 +63,11 @@ void bhv_small_water_wave_loop(void) {
|
|||
if (o->oPosY > sp1C) {
|
||||
o->activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
o->oPosY += 5.0f;
|
||||
if (gFreeObjectList.next != NULL)
|
||||
spawn_object(o, MODEL_SMALL_WATER_SPLASH, bhvObjectWaterSplash);
|
||||
traverse_object_pools(
|
||||
if (node != NULL && node->freeList.next != NULL) {
|
||||
spawn_object(o, MODEL_SMALL_WATER_SPLASH, bhvObjectWaterSplash);
|
||||
}
|
||||
)
|
||||
}
|
||||
if (o->oInteractStatus & INT_STATUS_INTERACTED)
|
||||
obj_mark_for_deletion(o);
|
||||
|
|
|
|||
|
|
@ -716,15 +716,17 @@ struct Object *try_to_spawn_object(s16 offsetY, f32 scale, struct Object *parent
|
|||
const BehaviorScript *behavior) {
|
||||
struct Object *obj;
|
||||
|
||||
if (gFreeObjectList.next != NULL) {
|
||||
traverse_object_pools(
|
||||
if (node == NULL || node->freeList.next == NULL) { return NULL; }
|
||||
|
||||
obj = spawn_object(parent, model, behavior);
|
||||
if (obj == NULL) { return NULL; }
|
||||
obj->oPosY += offsetY;
|
||||
obj_scale(obj, scale);
|
||||
return obj;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct Object *spawn_object_with_scale(struct Object *parent, s32 model, const BehaviorScript *behavior, f32 scale) {
|
||||
|
|
@ -2547,16 +2549,16 @@ void cur_obj_spawn_particles(struct SpawnParticlesInfo *info) {
|
|||
s32 numParticles = info->count;
|
||||
|
||||
// If there are a lot of objects already, limit the number of particles
|
||||
if (gPrevFrameObjectCount > (OBJECT_POOL_CAPACITY * 150 / 240) && numParticles > 10) {
|
||||
/*if (gPrevFrameObjectCount > (OBJECT_POOL_CAPACITY * 150 / 240) && numParticles > 10) {
|
||||
numParticles = 10;
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
// We're close to running out of object slots, so don't spawn particles at
|
||||
// all
|
||||
if (gPrevFrameObjectCount > (OBJECT_POOL_CAPACITY * 210 / 240)) {
|
||||
/*if (gPrevFrameObjectCount > (OBJECT_POOL_CAPACITY * 210 / 240)) {
|
||||
numParticles = 0;
|
||||
}
|
||||
}*/
|
||||
|
||||
for (i = 0; i < numParticles; i++) {
|
||||
scale = random_float() * (info->sizeRange * 0.1f) + info->sizeBase * 0.1f;
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ u32 gTimeStopState;
|
|||
/**
|
||||
* The pool that objects are allocated from.
|
||||
*/
|
||||
struct Object gObjectPool[OBJECT_POOL_CAPACITY];
|
||||
struct ObjectPoolNode gObjectPool = { 0 };
|
||||
|
||||
/**
|
||||
* A special object whose purpose is to act as a parent for macro objects.
|
||||
|
|
@ -87,8 +87,9 @@ struct ObjectNode *gObjectLists;
|
|||
|
||||
/**
|
||||
* A singly linked list of available slots in the object pool.
|
||||
* Now stored in gObjectPool.
|
||||
*/
|
||||
struct ObjectNode gFreeObjectList;
|
||||
//struct ObjectNode gFreeObjectList;
|
||||
|
||||
/**
|
||||
* The object representing Mario.
|
||||
|
|
@ -568,11 +569,20 @@ void spawn_objects_from_info(UNUSED s32 unused, struct SpawnInfo *spawnInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
void free_pool_nodes(struct ObjectPoolNode* node) {
|
||||
if (node->next == NULL) {
|
||||
free(node);
|
||||
return;
|
||||
}
|
||||
|
||||
free_pool_nodes(node->next);
|
||||
free(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear objects, dynamic surfaces, and some miscellaneous level data used by objects.
|
||||
*/
|
||||
void clear_objects(void) {
|
||||
s32 i;
|
||||
sync_objects_clear();
|
||||
gTHIWaterDrained = 0;
|
||||
gTimeStopState = 0;
|
||||
|
|
@ -586,19 +596,24 @@ void clear_objects(void) {
|
|||
gMarioStates[i].currentRoom = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < 60; i++) {
|
||||
for (s32 i = 0; i < 60; i++) {
|
||||
gDoorAdjacentRooms[i][0] = 0;
|
||||
gDoorAdjacentRooms[i][1] = 0;
|
||||
}
|
||||
|
||||
debug_unknown_level_select_check();
|
||||
|
||||
init_free_object_list();
|
||||
if (gObjectPool.next != NULL) {
|
||||
free_pool_nodes(gObjectPool.next);
|
||||
gObjectPool.next = NULL;
|
||||
}
|
||||
|
||||
init_free_object_list(&gObjectPool);
|
||||
clear_object_lists(gObjectListArray);
|
||||
|
||||
for (i = 0; i < OBJECT_POOL_CAPACITY; i++) {
|
||||
gObjectPool[i].activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
geo_reset_object_node(&gObjectPool[i].header.gfx);
|
||||
for (u32 i = 0; i < OBJECT_POOL_NODE_CAPACITY; i++) {
|
||||
gObjectPool.pool[i].activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
geo_reset_object_node(&gObjectPool.pool[i].header.gfx);
|
||||
}
|
||||
|
||||
gObjectLists = gObjectListArray;
|
||||
|
|
@ -607,13 +622,26 @@ void clear_objects(void) {
|
|||
geo_clear_interp_data();
|
||||
}
|
||||
|
||||
void reinit_objects(struct ObjectPoolNode* node) {
|
||||
init_free_object_list(node);
|
||||
|
||||
for (u32 i = 0; i < OBJECT_POOL_NODE_CAPACITY; i++) {
|
||||
node->pool[i].activeFlags = ACTIVE_FLAG_DEACTIVATED;
|
||||
geo_reset_object_node(&node->pool[i].header.gfx);
|
||||
}
|
||||
|
||||
clear_dynamic_surfaces();
|
||||
geo_clear_interp_data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update spawner and surface objects.
|
||||
*/
|
||||
void update_terrain_objects(void) {
|
||||
gObjectCounter = update_objects_in_list(&gObjectLists[OBJ_LIST_SPAWNER]);
|
||||
//! This was meant to be +=
|
||||
gObjectCounter = update_objects_in_list(&gObjectLists[OBJ_LIST_SURFACE]);
|
||||
// Since this counter does not affect gameplay at all, fix the bug
|
||||
gObjectCounter += update_objects_in_list(&gObjectLists[OBJ_LIST_SURFACE]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -22,8 +22,15 @@
|
|||
|
||||
/**
|
||||
* The maximum number of objects that can be loaded at once.
|
||||
* Kept for compatibility, but is unused.
|
||||
*/
|
||||
#define OBJECT_POOL_CAPACITY 1200
|
||||
#define OBJECT_POOL_CAPACITY 0xFFFFFFFF
|
||||
/**
|
||||
* The maximum number of objects that can be in a single pool node.
|
||||
* A higher number might be better for less fragmentation.
|
||||
* ! Can't seem to go above 256 without crashing in geo_reset_object_node()...
|
||||
*/
|
||||
#define OBJECT_POOL_NODE_CAPACITY 256
|
||||
|
||||
/**
|
||||
* Every object is categorized into an object list, which controls the order
|
||||
|
|
@ -58,6 +65,18 @@ enum ObjectList
|
|||
NUM_OBJ_LISTS
|
||||
};
|
||||
|
||||
struct ObjectPoolNode {
|
||||
struct Object pool[OBJECT_POOL_NODE_CAPACITY];
|
||||
struct ObjectNode freeList;
|
||||
struct ObjectPoolNode* next;
|
||||
};
|
||||
|
||||
#define traverse_object_pools(statements) \
|
||||
for (struct ObjectPoolNode* node = &gObjectPool; node != NULL; node = node->next) { \
|
||||
for (u32 i = 0; i < OBJECT_POOL_NODE_CAPACITY; i++) { \
|
||||
statements \
|
||||
} \
|
||||
} \
|
||||
|
||||
extern struct ObjectNode gObjectListArray[];
|
||||
|
||||
|
|
@ -79,10 +98,10 @@ extern s16 gDebugInfo[][8];
|
|||
extern s16 gDebugInfoOverwrite[][8];
|
||||
|
||||
extern u32 gTimeStopState;
|
||||
extern struct Object gObjectPool[];
|
||||
extern struct ObjectPoolNode gObjectPool;
|
||||
extern struct Object gMacroObjectDefaultParent;
|
||||
extern struct ObjectNode *gObjectLists;
|
||||
extern struct ObjectNode gFreeObjectList;
|
||||
//extern struct ObjectNode gFreeObjectList;
|
||||
|
||||
extern struct Object *gMarioObject;
|
||||
extern struct Object *gMarioObjects[];
|
||||
|
|
@ -118,6 +137,7 @@ void set_object_respawn_info_bits(struct Object *obj, u8 bits);
|
|||
void unload_objects_from_area(UNUSED s32 unused, s32 areaIndex);
|
||||
void spawn_objects_from_info(UNUSED s32 unused, struct SpawnInfo *spawnInfo);
|
||||
void clear_objects(void);
|
||||
void reinit_objects(struct ObjectPoolNode* node);
|
||||
void update_objects(UNUSED s32 unused);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -81,17 +81,22 @@ struct LinkedList *unused_try_allocate(struct LinkedList *destList,
|
|||
* to the end of destList (doubly linked). Return the object, or NULL if
|
||||
* freeList is empty.
|
||||
*/
|
||||
struct Object *try_allocate_object(struct ObjectNode *destList, struct ObjectNode *freeList) {
|
||||
struct Object* try_allocate_object(struct ObjectNode* destList, struct ObjectPoolNode* node) {
|
||||
struct ObjectNode *nextObj = NULL;
|
||||
|
||||
if (destList == NULL || freeList == NULL) {
|
||||
fprintf(stderr, "FATAL ERROR: Failed to try and allocate a object because either the destList %p or freeList %p was NULL!\n", destList, freeList);
|
||||
if (node == NULL) {
|
||||
fprintf(stderr, "FATAL ERROR: Failed to try and allocate an object because the pool %p was NULL!\n", node);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((nextObj = freeList->next) != NULL) {
|
||||
if (destList == NULL) {
|
||||
fprintf(stderr, "FATAL ERROR: Failed to try and allocate an object because the destList %p was NULL!\n", destList);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((nextObj = node->freeList.next) != NULL) {
|
||||
// Remove from free list
|
||||
freeList->next = nextObj->next;
|
||||
node->freeList.next = nextObj->next;
|
||||
|
||||
// Insert at end of destination list
|
||||
nextObj->prev = destList->prev;
|
||||
|
|
@ -103,7 +108,13 @@ struct Object *try_allocate_object(struct ObjectNode *destList, struct ObjectNod
|
|||
}
|
||||
destList->prev = nextObj;
|
||||
} else {
|
||||
return NULL;
|
||||
if (node->next != NULL) {
|
||||
return try_allocate_object(destList, node->next);
|
||||
}
|
||||
|
||||
node->next = (struct ObjectPoolNode*)calloc(1, sizeof(struct ObjectPoolNode));
|
||||
reinit_objects(node->next);
|
||||
return try_allocate_object(destList, node->next);
|
||||
}
|
||||
|
||||
geo_remove_child(&nextObj->gfx.node);
|
||||
|
|
@ -138,35 +149,40 @@ void unused_deallocate(struct LinkedList *freeList, struct LinkedList *node) {
|
|||
* Remove the given object from the object list that it's currently in, and
|
||||
* insert it at the beginning of the free list (singly linked).
|
||||
*/
|
||||
static void deallocate_object(struct ObjectNode *freeList, struct ObjectNode *obj) {
|
||||
if (!obj || !freeList) { return; }
|
||||
static void deallocate_object(struct ObjectNode *obj) {
|
||||
if (obj == NULL) { return; }
|
||||
// Remove from object list
|
||||
if (obj->next) { obj->next->prev = obj->prev; }
|
||||
if (obj->prev) { obj->prev->next = obj->next; }
|
||||
|
||||
// Insert at beginning of free list
|
||||
obj->next = freeList->next;
|
||||
freeList->next = obj;
|
||||
for (struct ObjectPoolNode* node = &gObjectPool; node != NULL; node = node->next) {
|
||||
if (node->freeList.next == NULL) { continue; }
|
||||
obj->next = node->freeList.next;
|
||||
node->freeList.next = obj;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add every object in the pool to the free object list.
|
||||
*/
|
||||
void init_free_object_list(void) {
|
||||
s32 poolLength = OBJECT_POOL_CAPACITY;
|
||||
void init_free_object_list(struct ObjectPoolNode* node) {
|
||||
if (node == NULL) { return; }
|
||||
|
||||
// Add the first object in the pool to the free list
|
||||
struct Object *obj = &gObjectPool[0];
|
||||
gFreeObjectList.next = (struct ObjectNode *) obj;
|
||||
struct Object *obj = &node->pool[0];
|
||||
node->freeList.next = (struct ObjectNode*)obj;
|
||||
|
||||
// Link each object in the pool to the following object
|
||||
for (s32 i = 0; i < poolLength - 1; i++) {
|
||||
for (s32 i = 0; i < OBJECT_POOL_NODE_CAPACITY - 1; i++) {
|
||||
obj->header.next = &(obj + 1)->header;
|
||||
obj++;
|
||||
}
|
||||
|
||||
// End the list
|
||||
obj->header.next = NULL;
|
||||
// Attach pool
|
||||
obj->header.pool = node;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -247,7 +263,7 @@ void unload_object(struct Object *obj) {
|
|||
|
||||
smlua_call_event_hooks(HOOK_ON_OBJECT_UNLOAD, obj);
|
||||
|
||||
deallocate_object(&gFreeObjectList, &obj->header);
|
||||
deallocate_object(&obj->header);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -257,7 +273,7 @@ void unload_object(struct Object *obj) {
|
|||
*/
|
||||
struct Object *allocate_object(struct ObjectNode *objList) {
|
||||
if (!objList) { return NULL; }
|
||||
struct Object *obj = try_allocate_object(objList, &gFreeObjectList);
|
||||
struct Object *obj = try_allocate_object(objList, &gObjectPool);
|
||||
|
||||
// The object list is full if the newly created pointer is NULL.
|
||||
// If this happens, we first attempt to unload unimportant objects
|
||||
|
|
@ -273,7 +289,7 @@ struct Object *allocate_object(struct ObjectNode *objList) {
|
|||
} else {
|
||||
// If an unimportant object does exist, unload it and take its slot.
|
||||
unload_object(unimportantObj);
|
||||
obj = try_allocate_object(objList, &gFreeObjectList);
|
||||
obj = try_allocate_object(objList, &gObjectPool);
|
||||
if (gCurrentObject == obj) {
|
||||
//! Uh oh, the unimportant object was in the middle of
|
||||
// updating! This could cause some interesting logic errors,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include "types.h"
|
||||
|
||||
void init_free_object_list(void);
|
||||
void init_free_object_list(struct ObjectPoolNode* node);
|
||||
void clear_object_lists(struct ObjectNode *objLists);
|
||||
void unload_object(struct Object *obj);
|
||||
struct Object *create_object(const BehaviorScript *bhvScript);
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "src/game/player_palette.h"
|
||||
#include "src/engine/graph_node.h"
|
||||
#include "include/PR/gbi.h"
|
||||
#include "src/game/object_list_processor.h"
|
||||
|
||||
#include "include/object_fields.h"
|
||||
|
||||
|
|
@ -1580,6 +1581,13 @@ static struct LuaObjectField sNetworkPlayerFields[LUA_NETWORK_PLAYER_FIELD_COUNT
|
|||
{ "type", LVT_U8, offsetof(struct NetworkPlayer, type), true, LOT_NONE, 1, sizeof(u8) },
|
||||
};
|
||||
|
||||
#define LUA_NUM_TIMES_CALLED_FIELD_COUNT 3
|
||||
static struct LuaObjectField sNumTimesCalledFields[LUA_NUM_TIMES_CALLED_FIELD_COUNT] = {
|
||||
{ "ceil", LVT_S16, offsetof(struct NumTimesCalled, ceil), false, LOT_NONE, 1, sizeof(s16) },
|
||||
{ "floor", LVT_S16, offsetof(struct NumTimesCalled, floor), false, LOT_NONE, 1, sizeof(s16) },
|
||||
{ "wall", LVT_S16, offsetof(struct NumTimesCalled, wall), false, LOT_NONE, 1, sizeof(s16) },
|
||||
};
|
||||
|
||||
#define LUA_OBJECT_FIELD_COUNT 763
|
||||
static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = {
|
||||
{ "activeFlags", LVT_S16, offsetof(struct Object, activeFlags), false, LOT_NONE, 1, sizeof(s16) },
|
||||
|
|
@ -2374,11 +2382,19 @@ static struct LuaObjectField sObjectHitboxFields[LUA_OBJECT_HITBOX_FIELD_COUNT]
|
|||
{ "radius", LVT_S16, offsetof(struct ObjectHitbox, radius), false, LOT_NONE, 1, sizeof(s16) },
|
||||
};
|
||||
|
||||
#define LUA_OBJECT_NODE_FIELD_COUNT 3
|
||||
#define LUA_OBJECT_NODE_FIELD_COUNT 4
|
||||
static struct LuaObjectField sObjectNodeFields[LUA_OBJECT_NODE_FIELD_COUNT] = {
|
||||
{ "gfx", LVT_COBJECT, offsetof(struct ObjectNode, gfx), true, LOT_GRAPHNODEOBJECT, 1, sizeof(struct GraphNodeObject) },
|
||||
{ "next", LVT_COBJECT_P, offsetof(struct ObjectNode, next), true, LOT_OBJECTNODE, 1, sizeof(struct ObjectNode*) },
|
||||
{ "prev", LVT_COBJECT_P, offsetof(struct ObjectNode, prev), true, LOT_OBJECTNODE, 1, sizeof(struct ObjectNode*) },
|
||||
{ "gfx", LVT_COBJECT, offsetof(struct ObjectNode, gfx), true, LOT_GRAPHNODEOBJECT, 1, sizeof(struct GraphNodeObject) },
|
||||
{ "next", LVT_COBJECT_P, offsetof(struct ObjectNode, next), true, LOT_OBJECTNODE, 1, sizeof(struct ObjectNode*) },
|
||||
{ "pool", LVT_COBJECT_P, offsetof(struct ObjectNode, pool), false, LOT_OBJECTPOOLNODE, 1, sizeof(struct ObjectPoolNode*) },
|
||||
{ "prev", LVT_COBJECT_P, offsetof(struct ObjectNode, prev), true, LOT_OBJECTNODE, 1, sizeof(struct ObjectNode*) },
|
||||
};
|
||||
|
||||
#define LUA_OBJECT_POOL_NODE_FIELD_COUNT 3
|
||||
static struct LuaObjectField sObjectPoolNodeFields[LUA_OBJECT_POOL_NODE_FIELD_COUNT] = {
|
||||
{ "freeList", LVT_COBJECT, offsetof(struct ObjectPoolNode, freeList), true, LOT_OBJECTNODE, 1, sizeof(struct ObjectNode) },
|
||||
{ "next", LVT_COBJECT_P, offsetof(struct ObjectPoolNode, next), false, LOT_OBJECTPOOLNODE, 1, sizeof(struct ObjectPoolNode*) },
|
||||
{ "pool", LVT_COBJECT, offsetof(struct ObjectPoolNode, pool), true, LOT_OBJECT, OBJECT_POOL_NODE_CAPACITY, sizeof(struct Object) },
|
||||
};
|
||||
|
||||
#define LUA_OBJECT_WARP_NODE_FIELD_COUNT 3
|
||||
|
|
@ -2736,9 +2752,11 @@ struct LuaObjectTable sLuaObjectAutogenTable[LOT_AUTOGEN_MAX - LOT_AUTOGEN_MIN]
|
|||
{ LOT_MODFSFILE, sModFsFileFields, LUA_MOD_FS_FILE_FIELD_COUNT },
|
||||
{ LOT_NAMETAGSSETTINGS, sNametagsSettingsFields, LUA_NAMETAGS_SETTINGS_FIELD_COUNT },
|
||||
{ LOT_NETWORKPLAYER, sNetworkPlayerFields, LUA_NETWORK_PLAYER_FIELD_COUNT },
|
||||
{ LOT_NUMTIMESCALLED, sNumTimesCalledFields, LUA_NUM_TIMES_CALLED_FIELD_COUNT },
|
||||
{ LOT_OBJECT, sObjectFields, LUA_OBJECT_FIELD_COUNT },
|
||||
{ LOT_OBJECTHITBOX, sObjectHitboxFields, LUA_OBJECT_HITBOX_FIELD_COUNT },
|
||||
{ LOT_OBJECTNODE, sObjectNodeFields, LUA_OBJECT_NODE_FIELD_COUNT },
|
||||
{ LOT_OBJECTPOOLNODE, sObjectPoolNodeFields, LUA_OBJECT_POOL_NODE_FIELD_COUNT },
|
||||
{ LOT_OBJECTWARPNODE, sObjectWarpNodeFields, LUA_OBJECT_WARP_NODE_FIELD_COUNT },
|
||||
{ LOT_PAINTING, sPaintingFields, LUA_PAINTING_FIELD_COUNT },
|
||||
{ LOT_PAINTINGVALUES, sPaintingValuesFields, LUA_PAINTING_VALUES_FIELD_COUNT },
|
||||
|
|
@ -2841,9 +2859,11 @@ const char *sLuaLotNames[] = {
|
|||
[LOT_MODFSFILE] = "ModFsFile",
|
||||
[LOT_NAMETAGSSETTINGS] = "NametagsSettings",
|
||||
[LOT_NETWORKPLAYER] = "NetworkPlayer",
|
||||
[LOT_NUMTIMESCALLED] = "NumTimesCalled",
|
||||
[LOT_OBJECT] = "Object",
|
||||
[LOT_OBJECTHITBOX] = "ObjectHitbox",
|
||||
[LOT_OBJECTNODE] = "ObjectNode",
|
||||
[LOT_OBJECTPOOLNODE] = "ObjectPoolNode",
|
||||
[LOT_OBJECTWARPNODE] = "ObjectWarpNode",
|
||||
[LOT_PAINTING] = "Painting",
|
||||
[LOT_PAINTINGVALUES] = "PaintingValues",
|
||||
|
|
|
|||
|
|
@ -86,9 +86,11 @@ enum LuaObjectAutogenType {
|
|||
LOT_MODFSFILE,
|
||||
LOT_NAMETAGSSETTINGS,
|
||||
LOT_NETWORKPLAYER,
|
||||
LOT_NUMTIMESCALLED,
|
||||
LOT_OBJECT,
|
||||
LOT_OBJECTHITBOX,
|
||||
LOT_OBJECTNODE,
|
||||
LOT_OBJECTPOOLNODE,
|
||||
LOT_OBJECTWARPNODE,
|
||||
LOT_PAINTING,
|
||||
LOT_PAINTINGVALUES,
|
||||
|
|
|
|||
|
|
@ -2976,7 +2976,8 @@ char gSmluaConstants[] = ""
|
|||
"TIME_STOP_ALL_OBJECTS=(1 << 4)\n"
|
||||
"TIME_STOP_MARIO_OPENED_DOOR=(1 << 5)\n"
|
||||
"TIME_STOP_ACTIVE=(1 << 6)\n"
|
||||
"OBJECT_POOL_CAPACITY=1200\n"
|
||||
"OBJECT_POOL_CAPACITY=0xFFFFFFFF\n"
|
||||
"OBJECT_POOL_NODE_CAPACITY=256\n"
|
||||
"OBJ_LIST_PLAYER=0\n"
|
||||
"OBJ_LIST_EXT=1\n"
|
||||
"OBJ_LIST_DESTRUCTIVE=2\n"
|
||||
|
|
|
|||
|
|
@ -35485,6 +35485,21 @@ int smlua_func_obj_anim_skip_interpolation(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_obj_get_count(UNUSED lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 0) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "obj_get_count", 0, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
lua_pushinteger(L, obj_get_count());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
// smlua_text_utils.h //
|
||||
////////////////////////
|
||||
|
|
@ -38753,6 +38768,7 @@ void smlua_bind_functions_autogen(void) {
|
|||
smlua_bind_function(L, "set_whirlpools", smlua_func_set_whirlpools);
|
||||
smlua_bind_function(L, "obj_skip_interpolation", smlua_func_obj_skip_interpolation);
|
||||
smlua_bind_function(L, "obj_anim_skip_interpolation", smlua_func_obj_anim_skip_interpolation);
|
||||
smlua_bind_function(L, "obj_get_count", smlua_func_obj_get_count);
|
||||
|
||||
// smlua_text_utils.h
|
||||
smlua_bind_function(L, "smlua_text_utils_reset_all", smlua_func_smlua_text_utils_reset_all);
|
||||
|
|
|
|||
|
|
@ -530,6 +530,10 @@ void obj_anim_skip_interpolation(struct Object *o) {
|
|||
if (o) { o->header.gfx.animInfo.prevAnimFrameTimestamp = 0; }
|
||||
}
|
||||
|
||||
u32 obj_get_count(void) {
|
||||
return gObjectCounter;
|
||||
}
|
||||
|
||||
#ifdef DEVELOPMENT
|
||||
void obj_randomize(struct Object* o) {
|
||||
if (!o) { return; }
|
||||
|
|
|
|||
|
|
@ -160,4 +160,7 @@ void obj_skip_interpolation(struct Object *o);
|
|||
/* |description|Skips animation interpolation for a frame|descriptionEnd| */
|
||||
void obj_anim_skip_interpolation(struct Object *o);
|
||||
|
||||
/* |description|Gets the amount of objects in this area|descriptionEnd| */
|
||||
u32 obj_get_count(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@
|
|||
|
||||
// TODO: move to common utility location
|
||||
static struct Object* get_object_matching_respawn_info(s16* respawnInfo) {
|
||||
for (s32 i = 0; i < OBJECT_POOL_CAPACITY; i++) {
|
||||
struct Object* o = &gObjectPool[i];
|
||||
traverse_object_pools(
|
||||
struct Object* o = &node->pool[i];
|
||||
if (o->respawnInfo == respawnInfo) { return o; }
|
||||
}
|
||||
)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -196,19 +196,19 @@ void network_receive_level_macro(struct Packet* p) {
|
|||
o->oCoinUnkF4 = (o->oBehParams >> 8) & 0xFF;
|
||||
|
||||
u8 childIndex = 0;
|
||||
for (s32 i = 0; i < OBJECT_POOL_CAPACITY; i++) {
|
||||
struct Object* o2 = &gObjectPool[i];
|
||||
traverse_object_pools(
|
||||
struct Object* o2 = &node->pool[i];
|
||||
if (o2->parentObj != o) { continue; }
|
||||
if (o2 == o) { continue; }
|
||||
if (o2->behavior != smlua_override_behavior(bhvCoinFormationSpawn) && o2->behavior != smlua_override_behavior(bhvYellowCoin)) { continue; }
|
||||
if (o->oCoinUnkF4 & (1 << childIndex++)) {
|
||||
obj_mark_for_deletion(o2);
|
||||
}
|
||||
}
|
||||
)
|
||||
LOG_INFO("rx macro special: coin formation");
|
||||
} else if (behavior == bhvGoombaTripletSpawner) {
|
||||
for (s32 i = 0; i < OBJECT_POOL_CAPACITY; i++) {
|
||||
struct Object* o2 = &gObjectPool[i];
|
||||
traverse_object_pools(
|
||||
struct Object* o2 = &node->pool[i];
|
||||
if (o2->parentObj != o) { continue; }
|
||||
if (o2 == o) { continue; }
|
||||
if (o2->behavior != smlua_override_behavior(bhvGoomba)) { continue; }
|
||||
|
|
@ -222,7 +222,7 @@ void network_receive_level_macro(struct Packet* p) {
|
|||
obj_mark_for_deletion(o2);
|
||||
gCurrentObject = prevObject;
|
||||
}
|
||||
}
|
||||
)
|
||||
LOG_INFO("rx macro special: goomba triplet");
|
||||
} else {
|
||||
o->oBehParams = (((*respawnInfo) & 0x00FF) << 16) + ((*respawnInfo) & 0xFF00);
|
||||
|
|
|
|||
|
|
@ -16,10 +16,10 @@
|
|||
|
||||
// TODO: move to common utility location
|
||||
static struct Object* get_object_matching_respawn_info(u32* respawnInfo) {
|
||||
for (s32 i = 0; i < OBJECT_POOL_CAPACITY; i++) {
|
||||
struct Object* o = &gObjectPool[i];
|
||||
traverse_object_pools(
|
||||
struct Object* o = &node->pool[i];
|
||||
if (o->respawnInfo == respawnInfo) { return o; }
|
||||
}
|
||||
)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue