From 1b99e2284870ce945200292e9aafadffb4368000 Mon Sep 17 00:00:00 2001 From: MysterD Date: Wed, 9 Mar 2022 18:59:55 -0800 Subject: [PATCH] Added the ability to spawn particles from Lua Added particles to football Increased the object cap for particles --- autogen/autogen.sh | 0 autogen/convert_structs.py | 1 + autogen/lua_constants/built-in.lua | 5 +- docs/lua/functions.md | 21 ++++++++ docs/lua/structs.md | 2 +- mods/football.lua | 68 +++++++++++++++++++++++-- src/game/behaviors/tree_particles.inc.c | 2 +- src/game/object_helpers.c | 5 +- src/pc/lua/smlua_cobject_autogen.c | 2 +- src/pc/lua/smlua_constants_autogen.c | 5 +- src/pc/lua/smlua_functions_autogen.c | 12 +++++ src/pc/lua/smlua_obj_utils.c | 13 +++++ src/pc/lua/smlua_obj_utils.h | 4 ++ src/pc/network/discord/user.c | 4 +- 14 files changed, 131 insertions(+), 13 deletions(-) mode change 100644 => 100755 autogen/autogen.sh diff --git a/autogen/autogen.sh b/autogen/autogen.sh old mode 100644 new mode 100755 diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index 222f90704..8cea014bf 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -68,6 +68,7 @@ override_field_immutable = { "TextureInfo": [ "*" ], "Object": ["oSyncID", "createdThroughNetwork"], "GlobalObjectAnimations": [ "*"], + "SpawnParticlesInfo": [ "model" ], } sLuaManuallyDefinedStructs = [ diff --git a/autogen/lua_constants/built-in.lua b/autogen/lua_constants/built-in.lua index c485e5403..138470c04 100644 --- a/autogen/lua_constants/built-in.lua +++ b/autogen/lua_constants/built-in.lua @@ -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 diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 686283974..5f5f79684 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -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
+## [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:](#) + +
+ ## [obj_has_behavior_id](#obj_has_behavior_id) ### Lua Example diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 07936a68a..d12abfa24 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -1655,7 +1655,7 @@ | forwardVelBase | `integer` | | | forwardVelRange | `integer` | | | gravity | `integer` | | -| model | `integer` | | +| model | `integer` | read-only | | offsetY | `integer` | | | sizeBase | `number` | | | sizeRange | `number` | | diff --git a/mods/football.lua b/mods/football.lua index 37579581c..84e6db971 100644 --- a/mods/football.lua +++ b/mods/football.lua @@ -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 diff --git a/src/game/behaviors/tree_particles.inc.c b/src/game/behaviors/tree_particles.inc.c index ad82b1f17..c2f69a30c 100644 --- a/src/game/behaviors/tree_particles.inc.c +++ b/src/game/behaviors/tree_particles.inc.c @@ -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; diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index abe9fa9e6..b82780c21 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -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; } diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index efb2a77b0..91569ed65 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -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 }, diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 53b8c22ce..6247f31e0 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -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" diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 276c4b262..3ade1085c 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -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); diff --git a/src/pc/lua/smlua_obj_utils.c b/src/pc/lua/smlua_obj_utils.c index c570a1368..dd46cdabe 100644 --- a/src/pc/lua/smlua_obj_utils.c +++ b/src/pc/lua/smlua_obj_utils.c @@ -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; +} diff --git a/src/pc/lua/smlua_obj_utils.h b/src/pc/lua/smlua_obj_utils.h index 494d7aa71..44e2405a1 100644 --- a/src/pc/lua/smlua_obj_utils.h +++ b/src/pc/lua/smlua_obj_utils.h @@ -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 diff --git a/src/pc/network/discord/user.c b/src/pc/network/discord/user.c index de06da1f1..bd49c4270 100644 --- a/src/pc/network/discord/user.c +++ b/src/pc/network/discord/user.c @@ -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;