diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index 9dab95e9..14dc529a 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -155,7 +155,9 @@ manual_documentation = """ ## [define_custom_obj_fields](#define_custom_obj_fields) -Defines a custom set of overlapping object fields. The `fieldTable` table's keys must start with the letter `o` and the values must be either `u32`, `s32`, or `f32`. +Defines a custom set of overlapping object fields. + +The `fieldTable` table's keys must start with the letter `o` and the values must be either `u32`, `s32`, or `f32`. ### Lua Example `define_custom_obj_fields({ oCustomField1 = 'u32', oCustomField2 = 's32', oCustomField3 = 'f32' })` diff --git a/docs/lua/examples/behavior-ball.lua b/docs/lua/examples/behavior-ball.lua new file mode 100644 index 00000000..2c91b520 --- /dev/null +++ b/docs/lua/examples/behavior-ball.lua @@ -0,0 +1,103 @@ +-- name: Ball +-- description: Press DPAD down to spawn a ball + +function bhv_ball_init(obj) + obj.oFlags = OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE + obj.oGraphYOffset = 35 + cur_obj_scale(1.0) + + -- physics + obj.oWallHitboxRadius = 40.00 + obj.oGravity = 2.50 + obj.oBounciness = -0.75 + obj.oDragStrength = 0.00 + obj.oFriction = 0.99 + obj.oBuoyancy = -2.00 + + -- hitbox + obj.hitboxRadius = 100 + obj.hitboxHeight = 100 + + network_init_object(obj, true, nil) +end + +function bhv_ball_loop(obj) + local m = nearest_mario_state_to_object(obj) + local player = m.marioObj + local distanceToPlayer = dist_between_objects(obj, player) + local angleToPlayer = obj_angle_to_object(obj, player) + local localPlayerTouch = false + + -- figure out player-to-ball radius + local radius = 100 + if (m.action & ACT_FLAG_ATTACKING) ~= 0 then + radius = 150 + end + + -- check if player should affect ball + if distanceToPlayer < radius then + local xdiff = player.oPosX - obj.oPosX + local zdiff = player.oPosZ - obj.oPosZ + + obj.oPosX = obj.oPosX - (radius - distanceToPlayer) / radius * xdiff; + obj.oPosZ = obj.oPosZ - (radius - distanceToPlayer) / radius * zdiff; + + obj.oMoveAngleYaw = angleToPlayer + 0x8000 + obj.oForwardVel = obj.oForwardVel + 10 + + if (m.action & ACT_FLAG_ATTACKING) ~= 0 then + obj.oVelY = obj.oVelY + 20.0 + end + if m.playerIndex == 0 then + localPlayerTouch = true + end + end + + -- do physics + local stepRc = object_step_without_floor_orient() + + -- play sounds + if stepRc == 1 then + cur_obj_play_sound_2(SOUND_GENERAL_BOX_LANDING_2) + elseif (stepRc & 1) ~= 0 then + if obj.oForwardVel > 20.0 then + cur_obj_play_sound_2(SOUND_ENV_SLIDING) + end + end + + -- check for floor death + local floor = cur_obj_update_floor_height_and_get_floor() + if floor ~= nil then + obj_check_floor_death(stepRc, floor) + end + + -- update visual rotation + obj.oFaceAngleYaw = obj.oMoveAngleYaw + obj.oFaceAnglePitch = obj.oFaceAnglePitch + obj.oForwardVel * 100 + + -- if we touched it, send an immediate update instead of waiting + if localPlayerTouch then + network_send_object(obj, false) + end +end + +id_bhvBall = hook_behavior(0, OBJ_LIST_DEFAULT, bhv_ball_init, bhv_ball_loop) + +function mario_update_local(m) + if (m.controller.buttonPressed & D_JPAD) ~= 0 then + -- spawn ball + spawn_sync_object( + id_bhvBall, + E_MODEL_SPINY_BALL, + m.pos.x + 150, m.pos.y, m.pos.z, + nil) + end +end + +function mario_update(m) + if m.playerIndex == 0 then + mario_update_local(m) + end +end + +hook_event(HOOK_MARIO_UPDATE, mario_update) \ No newline at end of file diff --git a/docs/lua/examples/behavior-goomba.lua b/docs/lua/examples/behavior-goomba.lua new file mode 100644 index 00000000..90e44c8c --- /dev/null +++ b/docs/lua/examples/behavior-goomba.lua @@ -0,0 +1,95 @@ +-- name: Custom Goomba +-- description: A terrible goomba replacement to be used as an example. + +-- define goomba's custom fields +define_custom_obj_fields({ + oCustomGoombaScale = 'f32', + oCustomGoombaTargetYaw = 'f32', + oCustomGoombaRelativeSpeed = 'f32', +}) + +function bhv_custom_goomba_init(obj) + -- set flags + obj.oFlags = (OBJ_FLAG_COMPUTE_ANGLE_TO_MARIO | OBJ_FLAG_COMPUTE_DIST_TO_MARIO | OBJ_FLAG_SET_FACE_YAW_TO_MOVE_YAW | OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE) + + -- drop to floor + local x = obj.oPosX + local y = obj.oPosY + local z = obj.oPosZ + local floor = find_floor_height(x, y + 200.0, z) + obj.oPosY = floor + obj.oMoveFlags = obj.oMoveFlags | OBJ_MOVE_ON_GROUND + + -- animations + obj.oAnimations = gObjectAnimations.goomba_seg8_anims_0801DA4C + + -- home + obj.oHomeX = obj.oPosX + obj.oHomeY = obj.oPosY + obj.oHomeZ = obj.oPosZ + + -- physics + obj.oWallHitboxRadius = 40.0 + obj.oGravity = -4.0 + obj.oBounciness = -0.5 + obj.oDragStrength = 10.0 + obj.oFriction = 10.0 + obj.oBuoyancy = 0.0 + + -- normal init + obj.oCustomGoombaScale = 1.5 + obj.oDeathSound = SOUND_OBJ_ENEMY_DEATH_HIGH + + -- hitbox + obj.oInteractType = INTERACT_BOUNCE_TOP + obj.oHealth = 0 + obj.oNumLootCoins = 1 + obj.oIntangibleTimer = 0 + obj.hitboxRadius = obj.header.gfx.scale.x * 72 + obj.hitboxHeight = obj.header.gfx.scale.y * 50 + obj.hurtboxRadius = obj.header.gfx.scale.x * 42 + obj.hurtboxHeight = obj.header.gfx.scale.y * 40 + obj.hitboxDownOffset = obj.header.gfx.scale.y * 0 + + -- other flags + obj.oDrawingDistance = 4000 + obj.oDamageOrCoinValue = 1 + obj.oGravity = -8.0 / 3.0 * obj.oCustomGoombaScale + + -- start synchronizing object + network_init_object(obj, true, { + 'oCustomGoombaScale', + 'oCustomGoombaTargetYaw', + 'oCustomGoombaRelativeSpeed', + }) +end + +function bhv_custom_goomba_loop(obj) + -- find player + local player = nearest_player_to_object(obj) + local distanceToPlayer = dist_between_objects(obj, player) + local angleToPlayer = obj_angle_to_object(obj, player) + + -- animate + cur_obj_init_animation_with_accel_and_sound(0, 5.0) + + -- update floor/walls and rotation + cur_obj_update_floor_and_walls() + obj.oCustomGoombaTargetYaw = angleToPlayer + cur_obj_rotate_yaw_toward(obj.oCustomGoombaTargetYaw, 0x200) + + -- set velocity + obj.oCustomGoombaRelativeSpeed = 80.0 + obj_forward_vel_approach(obj.oCustomGoombaRelativeSpeed * obj.oCustomGoombaScale, 0.4) + + -- perform physics + cur_obj_move_standard(-78) + + -- if goomba interacts, kill it + if (obj.oInteractStatus & INT_STATUS_INTERACTED) ~= 0 then + obj_mark_for_deletion(obj) + end +end + +-- hook the behavior +id_bhvCustomGoomba = hook_behavior(id_bhvGoomba, OBJ_LIST_PUSHABLE, bhv_custom_goomba_init, bhv_custom_goomba_loop) diff --git a/docs/lua/lua.md b/docs/lua/lua.md index a9912cb3..e940d70c 100644 --- a/docs/lua/lua.md +++ b/docs/lua/lua.md @@ -34,3 +34,5 @@ Lua scripts you make can be placed either the `mods` folder in the base director - [Hide and Seek](../../mods/hide-and-seek.lua) - [HUD Rendering](examples/hud.lua) - [Object Spawning](examples/spawn-stuff.lua) +- [Custom Ball Behavior](examples/behavior-ball.lua) +- [Replace Goomba Behavior](examples/behavior-goomba.lua)