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": [ "*" ],
|
||||
"Object": ["oSyncID", "createdThroughNetwork"],
|
||||
"GlobalObjectAnimations": [ "*"],
|
||||
"SpawnParticlesInfo": [ "model" ],
|
||||
}
|
||||
|
||||
sLuaManuallyDefinedStructs = [
|
||||
|
|
|
|||
|
|
@ -81,11 +81,12 @@ function vec3f_mul(dest, a)
|
|||
end
|
||||
|
||||
function vec3f_normalize(dest)
|
||||
local invsqrt = 1.0 / math.sqrt(dest.x * dest.x + dest.y * dest.y + dest.z * dest.z)
|
||||
if invsqrt == 0 then
|
||||
local divisor = math.sqrt(dest.x * dest.x + dest.y * dest.y + dest.z * dest.z)
|
||||
if divisor == 0 then
|
||||
return dest
|
||||
end
|
||||
|
||||
local invsqrt = 1.0 / divisor
|
||||
dest.x = dest.x * invsqrt
|
||||
dest.y = dest.y * 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_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_temp_spawn_particles_info](#obj_get_temp_spawn_particles_info)
|
||||
- [obj_has_behavior_id](#obj_has_behavior_id)
|
||||
- [obj_has_model_extended](#obj_has_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 />
|
||||
|
||||
## [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)
|
||||
|
||||
### Lua Example
|
||||
|
|
|
|||
|
|
@ -1655,7 +1655,7 @@
|
|||
| forwardVelBase | `integer` | |
|
||||
| forwardVelRange | `integer` | |
|
||||
| gravity | `integer` | |
|
||||
| model | `integer` | |
|
||||
| model | `integer` | read-only |
|
||||
| offsetY | `integer` | |
|
||||
| sizeBase | `number` | |
|
||||
| sizeRange | `number` | |
|
||||
|
|
|
|||
|
|
@ -163,6 +163,48 @@ define_custom_obj_fields({
|
|||
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)
|
||||
-- flags and such
|
||||
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 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.y = (cylPoint.y + differenceDir.y * (playerBallRadius + playerRadius + 1)) - objPoint.y
|
||||
|
|
@ -312,6 +356,11 @@ function bhv_ball_player_collision(obj)
|
|||
end
|
||||
end
|
||||
|
||||
-- make sure player has a velocity
|
||||
if not doReflection and vPlayerMag == 0 then
|
||||
doReflection = true
|
||||
end
|
||||
|
||||
--------------------------------------
|
||||
-- calculate velocity (interaction) --
|
||||
--------------------------------------
|
||||
|
|
@ -456,8 +505,10 @@ function bhv_ball_loop(obj)
|
|||
|
||||
-- detect normal along movement vector
|
||||
local vMag = vec3f_length(v)
|
||||
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) }
|
||||
if vMag > 0 then
|
||||
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(
|
||||
a.x, a.y, a.z,
|
||||
|
|
@ -467,6 +518,7 @@ function bhv_ball_loop(obj)
|
|||
local colNormals = {}
|
||||
if info.surface ~= nil then
|
||||
table.insert(colNormals, { x = info.surface.normal.x, y = info.surface.normal.y, z = info.surface.normal.z })
|
||||
bhv_ball_particle_bounce(obj)
|
||||
else
|
||||
table.insert(colNormals, nil)
|
||||
end
|
||||
|
|
@ -573,6 +625,16 @@ function bhv_ball_loop(obj)
|
|||
network_send_object(obj, false)
|
||||
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
|
||||
cb.oGlobalOwner = obj.oGlobalOwner
|
||||
cb.oHitTime = obj.oHitTime
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ void bhv_tree_snow_or_leaf_loop(void) {
|
|||
obj_mark_for_deletion(o);
|
||||
if (o->oTimer > 100)
|
||||
obj_mark_for_deletion(o);
|
||||
if (gPrevFrameObjectCount > 212)
|
||||
if (gPrevFrameObjectCount > (OBJECT_POOL_CAPACITY * 212 / 240))
|
||||
obj_mark_for_deletion(o);
|
||||
o->oFaceAnglePitch += o->oAngleVelPitch;
|
||||
o->oFaceAngleRoll += o->oAngleVelRoll;
|
||||
|
|
|
|||
|
|
@ -2238,13 +2238,14 @@ 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 > 150 && 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 > 210) {
|
||||
if (gPrevFrameObjectCount > (OBJECT_POOL_CAPACITY * 210 / 240)) {
|
||||
numParticles = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1439,7 +1439,7 @@ static struct LuaObjectField sSpawnParticlesInfoFields[LUA_SPAWN_PARTICLES_INFO_
|
|||
{ "forwardVelBase", LVT_S8, offsetof(struct SpawnParticlesInfo, forwardVelBase), false, LOT_NONE },
|
||||
{ "forwardVelRange", LVT_S8, offsetof(struct SpawnParticlesInfo, forwardVelRange), 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 },
|
||||
{ "sizeBase", LVT_F32, offsetof(struct SpawnParticlesInfo, sizeBase), false, LOT_NONE },
|
||||
{ "sizeRange", LVT_F32, offsetof(struct SpawnParticlesInfo, sizeRange), false, LOT_NONE },
|
||||
|
|
|
|||
|
|
@ -73,10 +73,11 @@ char gSmluaConstants[] = ""
|
|||
" return dest\n"
|
||||
"end\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"
|
||||
" if invsqrt == 0 then\n"
|
||||
" local divisor = math.sqrt(dest.x * dest.x + dest.y * dest.y + dest.z * dest.z)\n"
|
||||
" if divisor == 0 then\n"
|
||||
" return dest\n"
|
||||
" end\n"
|
||||
" local invsqrt = 1.0 / divisor\n"
|
||||
" dest.x = dest.x * invsqrt\n"
|
||||
" dest.y = dest.y * 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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_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_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_model_extended", smlua_func_obj_has_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;
|
||||
}
|
||||
|
||||
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_f32(struct Object *o, s32 fieldIndex, f32 value);
|
||||
|
||||
// misc obj helpers
|
||||
|
||||
struct SpawnParticlesInfo* obj_get_temp_spawn_particles_info(enum ModelExtendedId modelId);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@
|
|||
|
||||
static void on_current_user_update(UNUSED void* data) {
|
||||
LOGFILE_INFO(LFT_DISCORD, "> on_current_user_update");
|
||||
struct DiscordUser user;
|
||||
struct DiscordUser user = { 0 };
|
||||
app.users->get_current_user(app.users, &user);
|
||||
|
||||
// remember user id
|
||||
app.userId = user.id;
|
||||
gPcDebug.id = user.id;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue