mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
Added the ability to spawn particles from Lua
Added particles to football Increased the object cap for particles
This commit is contained in:
parent
f59513f3ae
commit
1b99e22848
14 changed files with 131 additions and 13 deletions
0
autogen/autogen.sh
Normal file → Executable file
0
autogen/autogen.sh
Normal file → Executable file
|
|
@ -68,6 +68,7 @@ override_field_immutable = {
|
||||||
"TextureInfo": [ "*" ],
|
"TextureInfo": [ "*" ],
|
||||||
"Object": ["oSyncID", "createdThroughNetwork"],
|
"Object": ["oSyncID", "createdThroughNetwork"],
|
||||||
"GlobalObjectAnimations": [ "*"],
|
"GlobalObjectAnimations": [ "*"],
|
||||||
|
"SpawnParticlesInfo": [ "model" ],
|
||||||
}
|
}
|
||||||
|
|
||||||
sLuaManuallyDefinedStructs = [
|
sLuaManuallyDefinedStructs = [
|
||||||
|
|
|
||||||
|
|
@ -81,11 +81,12 @@ function vec3f_mul(dest, a)
|
||||||
end
|
end
|
||||||
|
|
||||||
function vec3f_normalize(dest)
|
function vec3f_normalize(dest)
|
||||||
local invsqrt = 1.0 / math.sqrt(dest.x * dest.x + dest.y * dest.y + dest.z * dest.z)
|
local divisor = math.sqrt(dest.x * dest.x + dest.y * dest.y + dest.z * dest.z)
|
||||||
if invsqrt == 0 then
|
if divisor == 0 then
|
||||||
return dest
|
return dest
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local invsqrt = 1.0 / divisor
|
||||||
dest.x = dest.x * invsqrt
|
dest.x = dest.x * invsqrt
|
||||||
dest.y = dest.y * invsqrt
|
dest.y = dest.y * invsqrt
|
||||||
dest.z = dest.z * invsqrt
|
dest.z = dest.z * invsqrt
|
||||||
|
|
|
||||||
|
|
@ -631,6 +631,7 @@
|
||||||
- [obj_get_next_with_same_behavior_id](#obj_get_next_with_same_behavior_id)
|
- [obj_get_next_with_same_behavior_id](#obj_get_next_with_same_behavior_id)
|
||||||
- [obj_get_next_with_same_behavior_id_and_field_f32](#obj_get_next_with_same_behavior_id_and_field_f32)
|
- [obj_get_next_with_same_behavior_id_and_field_f32](#obj_get_next_with_same_behavior_id_and_field_f32)
|
||||||
- [obj_get_next_with_same_behavior_id_and_field_s32](#obj_get_next_with_same_behavior_id_and_field_s32)
|
- [obj_get_next_with_same_behavior_id_and_field_s32](#obj_get_next_with_same_behavior_id_and_field_s32)
|
||||||
|
- [obj_get_temp_spawn_particles_info](#obj_get_temp_spawn_particles_info)
|
||||||
- [obj_has_behavior_id](#obj_has_behavior_id)
|
- [obj_has_behavior_id](#obj_has_behavior_id)
|
||||||
- [obj_has_model_extended](#obj_has_model_extended)
|
- [obj_has_model_extended](#obj_has_model_extended)
|
||||||
- [obj_set_model_extended](#obj_set_model_extended)
|
- [obj_set_model_extended](#obj_set_model_extended)
|
||||||
|
|
@ -11595,6 +11596,26 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
|
## [obj_get_temp_spawn_particles_info](#obj_get_temp_spawn_particles_info)
|
||||||
|
|
||||||
|
### Lua Example
|
||||||
|
`local SpawnParticlesInfoValue = obj_get_temp_spawn_particles_info(modelId)`
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
| Field | Type |
|
||||||
|
| ----- | ---- |
|
||||||
|
| modelId | [enum ModelExtendedId](constants.md#enum-ModelExtendedId) |
|
||||||
|
|
||||||
|
### Returns
|
||||||
|
[SpawnParticlesInfo](structs.md#SpawnParticlesInfo)
|
||||||
|
|
||||||
|
### C Prototype
|
||||||
|
`struct SpawnParticlesInfo* obj_get_temp_spawn_particles_info(enum ModelExtendedId modelId);`
|
||||||
|
|
||||||
|
[:arrow_up_small:](#)
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
## [obj_has_behavior_id](#obj_has_behavior_id)
|
## [obj_has_behavior_id](#obj_has_behavior_id)
|
||||||
|
|
||||||
### Lua Example
|
### Lua Example
|
||||||
|
|
|
||||||
|
|
@ -1655,7 +1655,7 @@
|
||||||
| forwardVelBase | `integer` | |
|
| forwardVelBase | `integer` | |
|
||||||
| forwardVelRange | `integer` | |
|
| forwardVelRange | `integer` | |
|
||||||
| gravity | `integer` | |
|
| gravity | `integer` | |
|
||||||
| model | `integer` | |
|
| model | `integer` | read-only |
|
||||||
| offsetY | `integer` | |
|
| offsetY | `integer` | |
|
||||||
| sizeBase | `number` | |
|
| sizeBase | `number` | |
|
||||||
| sizeRange | `number` | |
|
| sizeRange | `number` | |
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,48 @@ define_custom_obj_fields({
|
||||||
oFrozen = 'u32',
|
oFrozen = 'u32',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function bhv_ball_particle_trail(obj)
|
||||||
|
local spi = obj_get_temp_spawn_particles_info(E_MODEL_SPARKLES)
|
||||||
|
if spi == nil then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
spi.behParam = 2
|
||||||
|
spi.count = 1
|
||||||
|
spi.offsetY = -1 * ballRadius
|
||||||
|
spi.forwardVelBase = 8
|
||||||
|
spi.forwardVelRange = 0
|
||||||
|
spi.velYBase = 6
|
||||||
|
spi.velYRange = 0
|
||||||
|
spi.gravity = 0
|
||||||
|
spi.dragStrength = 5
|
||||||
|
spi.sizeBase = 10
|
||||||
|
spi.sizeRange = 30
|
||||||
|
|
||||||
|
cur_obj_spawn_particles(spi)
|
||||||
|
end
|
||||||
|
|
||||||
|
function bhv_ball_particle_bounce(obj)
|
||||||
|
local spi = obj_get_temp_spawn_particles_info(E_MODEL_MIST)
|
||||||
|
if spi == nil then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
spi.behParam = 3
|
||||||
|
spi.count = 5
|
||||||
|
spi.offsetY = -1 * ballRadius
|
||||||
|
spi.forwardVelBase = 6
|
||||||
|
spi.forwardVelRange = -6
|
||||||
|
spi.velYBase = 6
|
||||||
|
spi.velYRange = -6
|
||||||
|
spi.gravity = 0
|
||||||
|
spi.dragStrength = 5
|
||||||
|
spi.sizeBase = 8
|
||||||
|
spi.sizeRange = 13
|
||||||
|
|
||||||
|
cur_obj_spawn_particles(spi)
|
||||||
|
end
|
||||||
|
|
||||||
function bhv_ball_init(obj)
|
function bhv_ball_init(obj)
|
||||||
-- flags and such
|
-- flags and such
|
||||||
obj.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE
|
obj.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE
|
||||||
|
|
@ -245,7 +287,9 @@ function bhv_ball_player_collision(obj)
|
||||||
|
|
||||||
local vDifference = { x = objPoint.x - cylPoint.x, y = objPoint.y - cylPoint.y, z = objPoint.z - cylPoint.z }
|
local vDifference = { x = objPoint.x - cylPoint.x, y = objPoint.y - cylPoint.y, z = objPoint.z - cylPoint.z }
|
||||||
local differenceDir = { x = vDifference.x, y = vDifference.y, z = vDifference.z }
|
local differenceDir = { x = vDifference.x, y = vDifference.y, z = vDifference.z }
|
||||||
vec3f_normalize(differenceDir)
|
if vec3f_length(differenceDir) ~= 0 then
|
||||||
|
vec3f_normalize(differenceDir)
|
||||||
|
end
|
||||||
|
|
||||||
alterPos.x = (cylPoint.x + differenceDir.x * (playerBallRadius + playerRadius + 1)) - objPoint.x
|
alterPos.x = (cylPoint.x + differenceDir.x * (playerBallRadius + playerRadius + 1)) - objPoint.x
|
||||||
alterPos.y = (cylPoint.y + differenceDir.y * (playerBallRadius + playerRadius + 1)) - objPoint.y
|
alterPos.y = (cylPoint.y + differenceDir.y * (playerBallRadius + playerRadius + 1)) - objPoint.y
|
||||||
|
|
@ -312,6 +356,11 @@ function bhv_ball_player_collision(obj)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- make sure player has a velocity
|
||||||
|
if not doReflection and vPlayerMag == 0 then
|
||||||
|
doReflection = true
|
||||||
|
end
|
||||||
|
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
-- calculate velocity (interaction) --
|
-- calculate velocity (interaction) --
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
@ -456,8 +505,10 @@ function bhv_ball_loop(obj)
|
||||||
|
|
||||||
-- detect normal along movement vector
|
-- detect normal along movement vector
|
||||||
local vMag = vec3f_length(v)
|
local vMag = vec3f_length(v)
|
||||||
local vNorm = { x = v.x / vMag, y = v.y / vMag, z = v.z / vMag }
|
if vMag > 0 then
|
||||||
b = { x = v.x + vNorm.x * (vMag + ballRadius), y = v.y + vNorm.y * (vMag + ballRadius), z = v.z + vNorm.z * (vMag + ballRadius) }
|
local vNorm = { x = v.x / vMag, y = v.y / vMag, z = v.z / vMag }
|
||||||
|
b = { x = v.x + vNorm.x * (vMag + ballRadius), y = v.y + vNorm.y * (vMag + ballRadius), z = v.z + vNorm.z * (vMag + ballRadius) }
|
||||||
|
end
|
||||||
|
|
||||||
info = collision_find_surface_on_ray(
|
info = collision_find_surface_on_ray(
|
||||||
a.x, a.y, a.z,
|
a.x, a.y, a.z,
|
||||||
|
|
@ -467,6 +518,7 @@ function bhv_ball_loop(obj)
|
||||||
local colNormals = {}
|
local colNormals = {}
|
||||||
if info.surface ~= nil then
|
if info.surface ~= nil then
|
||||||
table.insert(colNormals, { x = info.surface.normal.x, y = info.surface.normal.y, z = info.surface.normal.z })
|
table.insert(colNormals, { x = info.surface.normal.x, y = info.surface.normal.y, z = info.surface.normal.z })
|
||||||
|
bhv_ball_particle_bounce(obj)
|
||||||
else
|
else
|
||||||
table.insert(colNormals, nil)
|
table.insert(colNormals, nil)
|
||||||
end
|
end
|
||||||
|
|
@ -573,6 +625,16 @@ function bhv_ball_loop(obj)
|
||||||
network_send_object(obj, false)
|
network_send_object(obj, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- spawn a particle trail
|
||||||
|
if vMag > 50 then
|
||||||
|
bhv_ball_particle_trail(obj)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- hack: make sure we never set velocity to nan
|
||||||
|
if obj.oVelX ~= obj.oVelX then obj.oVelX = 0 end
|
||||||
|
if obj.oVelY ~= obj.oVelY then obj.oVelY = 0 end
|
||||||
|
if obj.oVelZ ~= obj.oVelZ then obj.oVelZ = 0 end
|
||||||
|
|
||||||
-- hack: save pos/vel to detect packets
|
-- hack: save pos/vel to detect packets
|
||||||
cb.oGlobalOwner = obj.oGlobalOwner
|
cb.oGlobalOwner = obj.oGlobalOwner
|
||||||
cb.oHitTime = obj.oHitTime
|
cb.oHitTime = obj.oHitTime
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ void bhv_tree_snow_or_leaf_loop(void) {
|
||||||
obj_mark_for_deletion(o);
|
obj_mark_for_deletion(o);
|
||||||
if (o->oTimer > 100)
|
if (o->oTimer > 100)
|
||||||
obj_mark_for_deletion(o);
|
obj_mark_for_deletion(o);
|
||||||
if (gPrevFrameObjectCount > 212)
|
if (gPrevFrameObjectCount > (OBJECT_POOL_CAPACITY * 212 / 240))
|
||||||
obj_mark_for_deletion(o);
|
obj_mark_for_deletion(o);
|
||||||
o->oFaceAnglePitch += o->oAngleVelPitch;
|
o->oFaceAnglePitch += o->oAngleVelPitch;
|
||||||
o->oFaceAngleRoll += o->oAngleVelRoll;
|
o->oFaceAngleRoll += o->oAngleVelRoll;
|
||||||
|
|
|
||||||
|
|
@ -2238,13 +2238,14 @@ void cur_obj_spawn_particles(struct SpawnParticlesInfo *info) {
|
||||||
s32 numParticles = info->count;
|
s32 numParticles = info->count;
|
||||||
|
|
||||||
// If there are a lot of objects already, limit the number of particles
|
// If there are a lot of objects already, limit the number of particles
|
||||||
if (gPrevFrameObjectCount > 150 && numParticles > 10) {
|
if (gPrevFrameObjectCount > (OBJECT_POOL_CAPACITY * 150 / 240) && numParticles > 10) {
|
||||||
numParticles = 10;
|
numParticles = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// We're close to running out of object slots, so don't spawn particles at
|
// We're close to running out of object slots, so don't spawn particles at
|
||||||
// all
|
// all
|
||||||
if (gPrevFrameObjectCount > 210) {
|
if (gPrevFrameObjectCount > (OBJECT_POOL_CAPACITY * 210 / 240)) {
|
||||||
numParticles = 0;
|
numParticles = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1439,7 +1439,7 @@ static struct LuaObjectField sSpawnParticlesInfoFields[LUA_SPAWN_PARTICLES_INFO_
|
||||||
{ "forwardVelBase", LVT_S8, offsetof(struct SpawnParticlesInfo, forwardVelBase), false, LOT_NONE },
|
{ "forwardVelBase", LVT_S8, offsetof(struct SpawnParticlesInfo, forwardVelBase), false, LOT_NONE },
|
||||||
{ "forwardVelRange", LVT_S8, offsetof(struct SpawnParticlesInfo, forwardVelRange), false, LOT_NONE },
|
{ "forwardVelRange", LVT_S8, offsetof(struct SpawnParticlesInfo, forwardVelRange), false, LOT_NONE },
|
||||||
{ "gravity", LVT_S8, offsetof(struct SpawnParticlesInfo, gravity), false, LOT_NONE },
|
{ "gravity", LVT_S8, offsetof(struct SpawnParticlesInfo, gravity), false, LOT_NONE },
|
||||||
{ "model", LVT_U8, offsetof(struct SpawnParticlesInfo, model), false, LOT_NONE },
|
{ "model", LVT_U8, offsetof(struct SpawnParticlesInfo, model), true, LOT_NONE },
|
||||||
{ "offsetY", LVT_S8, offsetof(struct SpawnParticlesInfo, offsetY), false, LOT_NONE },
|
{ "offsetY", LVT_S8, offsetof(struct SpawnParticlesInfo, offsetY), false, LOT_NONE },
|
||||||
{ "sizeBase", LVT_F32, offsetof(struct SpawnParticlesInfo, sizeBase), false, LOT_NONE },
|
{ "sizeBase", LVT_F32, offsetof(struct SpawnParticlesInfo, sizeBase), false, LOT_NONE },
|
||||||
{ "sizeRange", LVT_F32, offsetof(struct SpawnParticlesInfo, sizeRange), false, LOT_NONE },
|
{ "sizeRange", LVT_F32, offsetof(struct SpawnParticlesInfo, sizeRange), false, LOT_NONE },
|
||||||
|
|
|
||||||
|
|
@ -73,10 +73,11 @@ char gSmluaConstants[] = ""
|
||||||
" return dest\n"
|
" return dest\n"
|
||||||
"end\n"
|
"end\n"
|
||||||
"function vec3f_normalize(dest)\n"
|
"function vec3f_normalize(dest)\n"
|
||||||
" local invsqrt = 1.0 / math.sqrt(dest.x * dest.x + dest.y * dest.y + dest.z * dest.z)\n"
|
" local divisor = math.sqrt(dest.x * dest.x + dest.y * dest.y + dest.z * dest.z)\n"
|
||||||
" if invsqrt == 0 then\n"
|
" if divisor == 0 then\n"
|
||||||
" return dest\n"
|
" return dest\n"
|
||||||
" end\n"
|
" end\n"
|
||||||
|
" local invsqrt = 1.0 / divisor\n"
|
||||||
" dest.x = dest.x * invsqrt\n"
|
" dest.x = dest.x * invsqrt\n"
|
||||||
" dest.y = dest.y * invsqrt\n"
|
" dest.y = dest.y * invsqrt\n"
|
||||||
" dest.z = dest.z * invsqrt\n"
|
" dest.z = dest.z * invsqrt\n"
|
||||||
|
|
|
||||||
|
|
@ -7397,6 +7397,17 @@ int smlua_func_obj_get_next_with_same_behavior_id_and_field_s32(lua_State* L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int smlua_func_obj_get_temp_spawn_particles_info(lua_State* L) {
|
||||||
|
if(!smlua_functions_valid_param_count(L, 1)) { return 0; }
|
||||||
|
|
||||||
|
int modelId = smlua_to_integer(L, 1);
|
||||||
|
if (!gSmLuaConvertSuccess) { return 0; }
|
||||||
|
|
||||||
|
smlua_push_object(L, LOT_SPAWNPARTICLESINFO, obj_get_temp_spawn_particles_info(modelId));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int smlua_func_obj_has_behavior_id(lua_State* L) {
|
int smlua_func_obj_has_behavior_id(lua_State* L) {
|
||||||
if(!smlua_functions_valid_param_count(L, 2)) { return 0; }
|
if(!smlua_functions_valid_param_count(L, 2)) { return 0; }
|
||||||
|
|
||||||
|
|
@ -8519,6 +8530,7 @@ void smlua_bind_functions_autogen(void) {
|
||||||
smlua_bind_function(L, "obj_get_next_with_same_behavior_id", smlua_func_obj_get_next_with_same_behavior_id);
|
smlua_bind_function(L, "obj_get_next_with_same_behavior_id", smlua_func_obj_get_next_with_same_behavior_id);
|
||||||
smlua_bind_function(L, "obj_get_next_with_same_behavior_id_and_field_f32", smlua_func_obj_get_next_with_same_behavior_id_and_field_f32);
|
smlua_bind_function(L, "obj_get_next_with_same_behavior_id_and_field_f32", smlua_func_obj_get_next_with_same_behavior_id_and_field_f32);
|
||||||
smlua_bind_function(L, "obj_get_next_with_same_behavior_id_and_field_s32", smlua_func_obj_get_next_with_same_behavior_id_and_field_s32);
|
smlua_bind_function(L, "obj_get_next_with_same_behavior_id_and_field_s32", smlua_func_obj_get_next_with_same_behavior_id_and_field_s32);
|
||||||
|
smlua_bind_function(L, "obj_get_temp_spawn_particles_info", smlua_func_obj_get_temp_spawn_particles_info);
|
||||||
smlua_bind_function(L, "obj_has_behavior_id", smlua_func_obj_has_behavior_id);
|
smlua_bind_function(L, "obj_has_behavior_id", smlua_func_obj_has_behavior_id);
|
||||||
smlua_bind_function(L, "obj_has_model_extended", smlua_func_obj_has_model_extended);
|
smlua_bind_function(L, "obj_has_model_extended", smlua_func_obj_has_model_extended);
|
||||||
smlua_bind_function(L, "obj_set_model_extended", smlua_func_obj_set_model_extended);
|
smlua_bind_function(L, "obj_set_model_extended", smlua_func_obj_set_model_extended);
|
||||||
|
|
|
||||||
|
|
@ -190,3 +190,16 @@ struct Object *obj_get_next_with_same_behavior_id_and_field_f32(struct Object *o
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SpawnParticlesInfo* obj_get_temp_spawn_particles_info(enum ModelExtendedId modelId) {
|
||||||
|
static struct SpawnParticlesInfo spi = { 0 };
|
||||||
|
|
||||||
|
u8 loadedModelId = smlua_model_util_load(modelId);
|
||||||
|
if (loadedModelId == 0xFF) {
|
||||||
|
LOG_ERROR("failed to load model %u", modelId);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
spi.model = loadedModelId;
|
||||||
|
|
||||||
|
return &spi;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,8 @@ struct Object *obj_get_next_with_same_behavior_id(struct Object *o);
|
||||||
struct Object *obj_get_next_with_same_behavior_id_and_field_s32(struct Object *o, s32 fieldIndex, s32 value);
|
struct Object *obj_get_next_with_same_behavior_id_and_field_s32(struct Object *o, s32 fieldIndex, s32 value);
|
||||||
struct Object *obj_get_next_with_same_behavior_id_and_field_f32(struct Object *o, s32 fieldIndex, f32 value);
|
struct Object *obj_get_next_with_same_behavior_id_and_field_f32(struct Object *o, s32 fieldIndex, f32 value);
|
||||||
|
|
||||||
|
// misc obj helpers
|
||||||
|
|
||||||
|
struct SpawnParticlesInfo* obj_get_temp_spawn_particles_info(enum ModelExtendedId modelId);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,10 @@
|
||||||
|
|
||||||
static void on_current_user_update(UNUSED void* data) {
|
static void on_current_user_update(UNUSED void* data) {
|
||||||
LOGFILE_INFO(LFT_DISCORD, "> on_current_user_update");
|
LOGFILE_INFO(LFT_DISCORD, "> on_current_user_update");
|
||||||
struct DiscordUser user;
|
struct DiscordUser user = { 0 };
|
||||||
app.users->get_current_user(app.users, &user);
|
app.users->get_current_user(app.users, &user);
|
||||||
|
|
||||||
|
// remember user id
|
||||||
app.userId = user.id;
|
app.userId = user.id;
|
||||||
gPcDebug.id = user.id;
|
gPcDebug.id = user.id;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue