diff --git a/configure.py b/configure.py index 217e9ee54..3223076e3 100644 --- a/configure.py +++ b/configure.py @@ -463,7 +463,7 @@ def MatchingFor(*versions): Object(Matching, "SB/Core/x/xRMemData.cpp", extra_cflags=["-sym on"]), Object(Matching, "SB/Core/x/xFactory.cpp"), Object(NonMatching, "SB/Core/x/xNPCBasic.cpp"), - Object(NonMatching, "SB/Game/zEntPlayerBungeeState.cpp"), + Object(NonMatching, "SB/Game/zEntPlayerBungeeState.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Game/zCollGeom.cpp"), Object(NonMatching, "SB/Core/x/xParSys.cpp"), Object(NonMatching, "SB/Core/x/xParEmitter.cpp"), diff --git a/src/SB/Core/x/xDebug.h b/src/SB/Core/x/xDebug.h index 4889866e2..d9ca11d03 100644 --- a/src/SB/Core/x/xDebug.h +++ b/src/SB/Core/x/xDebug.h @@ -7,6 +7,87 @@ extern U32 gFrameCount; +struct uint_data +{ + U32 value_def; + U32 value_min; + U32 value_max; +}; + +struct float_data +{ + F32 value_def; + F32 value_min; + F32 value_max; +}; + +struct bool_data +{ + U8 value_def; +}; + +struct select_data +{ + U32 value_def; + U32 labels_size; + char** labels; + void* values; +}; + +struct flag_data +{ + U32 value_def; + U32 mask; +}; + +struct raw_data +{ + U8 pad[16]; +}; + +struct int_data +{ + S32 value_def; + S32 value_min; + S32 value_max; +}; + +struct tweak_callback; +struct tweak_info +{ + substr name; + void* value; + tweak_callback* cb; + void* context; + U8 type; + U8 value_size; + U16 flags; + union + { + int_data int_context; + uint_data uint_context; + float_data float_context; + bool_data bool_context; + select_data select_context; + flag_data flag_context; + raw_data all_context; + }; +}; + +struct tweak_callback +{ + void (*on_change)(tweak_info&); + void (*on_select)(tweak_info&); + void (*on_unselect)(tweak_info&); + void (*on_start_edit)(tweak_info&); + void (*on_stop_edit)(tweak_info&); + void (*on_expand)(tweak_info&); + void (*on_collapse)(tweak_info&); + void (*on_update)(tweak_info&); + void (*convert_mem_to_tweak)(tweak_info&, void*); + void (*convert_tweak_to_mem)(tweak_info&, void*); +}; + void xprintf(const char* msg, ...); S32 xDebugModeAdd(char* mode, void(*debugFunc)); void xDebugInit(); @@ -14,6 +95,7 @@ void xDebugUpdate(); void xDebugExit(); void xDebugTimestampScreen(); +void xDebugAddTweak(const char*, F32*, F32, F32, const tweak_callback*, void*, U32); void xDebugRemoveTweak(const char*); void xDebugUpdate(); diff --git a/src/SB/Core/x/xFX.h b/src/SB/Core/x/xFX.h index 18bbc9abf..d09479ad1 100644 --- a/src/SB/Core/x/xFX.h +++ b/src/SB/Core/x/xFX.h @@ -8,6 +8,8 @@ #include #include +class xModelInstance; + struct xFXRing { U32 texture; @@ -120,6 +122,7 @@ void xFXRibbonRender(); void xFXAuraInit(); void xFXAuraUpdate(F32 dt); void xFXAuraRender(); +void xFXRenderProximityFade(const xModelInstance& model, F32 near_dist, F32 far_dist); void xFXSceneInit(); void xFXSceneSetup(); void xFXSceneReset(); diff --git a/src/SB/Core/x/xMath.h b/src/SB/Core/x/xMath.h index 2c5712d7c..8f1ca7f21 100644 --- a/src/SB/Core/x/xMath.h +++ b/src/SB/Core/x/xMath.h @@ -13,7 +13,7 @@ #define SQR(x) ((x) * (x)) -#define ALIGN(x, a) ((x) + ((a) - 1) & ~((a) - 1)) +#define ALIGN(x, a) ((x) + ((a)-1) & ~((a)-1)) // Override these to point to their corresponding symbols in .sdata2 // For example: @@ -28,6 +28,7 @@ #define RAD2DEG(x) ((ONEEIGHTY) * (x) / (PI)) #define FLOAT_MAX 1e38f +#define FLOAT_MIN -1e38f struct xFuncPiece { diff --git a/src/SB/Core/x/xMath3.h b/src/SB/Core/x/xMath3.h index a98b4dac9..5d683b3de 100644 --- a/src/SB/Core/x/xMath3.h +++ b/src/SB/Core/x/xMath3.h @@ -98,6 +98,7 @@ void xMat3x3Tolocal(xVec3* o, const xMat3x3* m, const xVec3* v); void xMat4x3MoveLocalRight(xMat4x3* m, F32 mag); void xMat4x3MoveLocalAt(xMat4x3* m, F32 mag); void xMat4x3MoveLocalUp(xMat4x3* m, F32 mag); +void xMat4x3OrthoInv(xMat4x3* o, const xMat4x3* m); void xMat3x3GetEuler(const xMat3x3* m, xVec3* a); void xMat3x3Euler(xMat3x3* m, const xVec3* ypr); void xQuatToMat(const xQuat* q, xMat3x3* m); diff --git a/src/SB/Core/x/xShadow.h b/src/SB/Core/x/xShadow.h index e3d1822c6..1947f1323 100644 --- a/src/SB/Core/x/xShadow.h +++ b/src/SB/Core/x/xShadow.h @@ -39,5 +39,6 @@ void xShadowSetLight(xVec3* param1, xVec3* param2, F32 param3); void xShadowManager_Init(S32 numEnts); void xShadowManager_Reset(); void xShadowManager_Render(); +void xShadowRender(xEnt* ent, F32 max_dist); #endif diff --git a/src/SB/Core/x/xVec3.h b/src/SB/Core/x/xVec3.h index 21a38ceb6..d7b38e5e8 100644 --- a/src/SB/Core/x/xVec3.h +++ b/src/SB/Core/x/xVec3.h @@ -21,6 +21,8 @@ struct xVec3 x = y = z = f; return *this; } + // FIXME: This should not be declared. Declaring it causes the assignment operator for the + // anonymous struct "camera" in hook_asset to call it rather than just copy the vec members. xVec3& operator=(const xVec3&); xVec3 operator+(const xVec3&) const; xVec3 operator-(const xVec3&) const; diff --git a/src/SB/Game/zEntCruiseBubble.h b/src/SB/Game/zEntCruiseBubble.h index 2581cfd57..19ded2cc5 100644 --- a/src/SB/Game/zEntCruiseBubble.h +++ b/src/SB/Game/zEntCruiseBubble.h @@ -2,6 +2,8 @@ #define ZENTCRUISEBUBBLE_H +#include "xDebug.h" + #include "zNPCHazard.h" #include "zShrapnel.h" #include @@ -14,6 +16,7 @@ // probably working on one of the bosses which also seem to use this. // As of now I'm not sure if you should include this declaration, // define your own or find a good place for shared use. +// NOTE (Square): pretty sure this is from xDebug namespace auto_tweak { template @@ -26,29 +29,29 @@ namespace cruise_bubble { enum state_enum { - BEGIN_STATE_PLAYER, - STATE_PLAYER_HALT = 0x0, - STATE_PLAYER_AIM, - STATE_PLAYER_FIRE, - STATE_PLAYER_WAIT, - END_STATE_PLAYER, - BEGIN_STATE_MISSLE = 0x4, - BACKUP_STATE_MISSLE = 0x3, - STATE_MISSLE_APPEAR, - STATE_MISSLE_FLY, - STATE_MISSLE_EXPLODE, - END_STATE_MISSLE, - BEGIN_STATE_CAMERA = 0x7, - BACKUP_STATE_CAMERA = 0x6, - STATE_CAMERA_AIM, - STATE_CAMERA_SEIZE, - STATE_CAMERA_ATTACH, - STATE_CAMERA_SURVEY, - STATE_CAMERA_RESTORE, - END_STATE_CAMERA, - MAX_STATE = 0xc, - BACKUP_STATE_PLAYER = 0xffffffff, - STATE_INVALID = 0xffffffff + BEGIN_STATE_PLAYER, + STATE_PLAYER_HALT = 0x0, + STATE_PLAYER_AIM, + STATE_PLAYER_FIRE, + STATE_PLAYER_WAIT, + END_STATE_PLAYER, + BEGIN_STATE_MISSLE = 0x4, + BACKUP_STATE_MISSLE = 0x3, + STATE_MISSLE_APPEAR, + STATE_MISSLE_FLY, + STATE_MISSLE_EXPLODE, + END_STATE_MISSLE, + BEGIN_STATE_CAMERA = 0x7, + BACKUP_STATE_CAMERA = 0x6, + STATE_CAMERA_AIM, + STATE_CAMERA_SEIZE, + STATE_CAMERA_ATTACH, + STATE_CAMERA_SURVEY, + STATE_CAMERA_RESTORE, + END_STATE_CAMERA, + MAX_STATE = 0xc, + BACKUP_STATE_PLAYER = 0xffffffff, + STATE_INVALID = 0xffffffff }; enum thread_enum @@ -307,21 +310,21 @@ namespace cruise_bubble { F32 life; F32 hit_dist; // 0x18 - F32 crash_angle; // 0x1c - F32 collide_twist; // 0x20 - S32 hit_tests; // 0x24 + F32 crash_angle; // 0x1c + F32 collide_twist; // 0x20 + S32 hit_tests; // 0x24 struct _class_27 { - F32 delay_show; // 0x28 - F32 delay_fly; // 0x2c - xVec3 offset; // 0x30 + F32 delay_show; // 0x28 + F32 delay_fly; // 0x2c + xVec3 offset; // 0x30 } appear; struct _class_32 { - F32 accel; // 0x3c - F32 max_vel; // 0x40 - F32 engine_pitch_max; // 0x44 - F32 engine_pitch_sensitivity; // 0x48 + F32 accel; // 0x3c + F32 max_vel; // 0x40 + F32 engine_pitch_max; // 0x44 + F32 engine_pitch_sensitivity; // 0x48 // Offset: 0x4c F32 flash_interval; struct _class_38 @@ -385,7 +388,7 @@ namespace cruise_bubble struct _class_48 { F32 env_alpha; - F32 env_coeff; // 0xd0 + F32 env_coeff; // 0xd0 U32 env_texture; // 0xd4 F32 fresnel_alpha; // 0xd8 F32 fresnel_coeff; // 0xdc @@ -554,7 +557,7 @@ namespace cruise_bubble missle_record_data(const xVec3& loc, F32 roll); }; - } + } // namespace void init_sound(); void stop_sound(S32 which, U32 handle); diff --git a/src/SB/Game/zEntPlayerBungeeState.cpp b/src/SB/Game/zEntPlayerBungeeState.cpp index e966cb3f2..dc947c8e9 100644 --- a/src/SB/Game/zEntPlayerBungeeState.cpp +++ b/src/SB/Game/zEntPlayerBungeeState.cpp @@ -1,57 +1,106 @@ #include "zEntPlayerBungeeState.h" +#include "xBound.h" +#include "xDebug.h" +#include "xFX.h" +#include "xMath.h" +#include "xMathInlines.h" #include "xMath3.h" +#include "xMarkerAsset.h" #include "xModel.h" +#include "xShadow.h" #include "xVec3.h" +#include "zEntCruiseBubble.h" #include "zEntPlayer.h" #include "zGameExtras.h" #include "zGlobals.h" +#include "zLightning.h" #include namespace bungee_state { namespace { - static class /* @class */ + struct drop_asset : xDynAsset { - // total size: 0x19C - public: - signed int flags; // offset 0x0, size 0x4 - class state_type* state; // offset 0x4, size 0x4 - class state_type* states[2]; // offset 0x8, size 0x8 - class /* @class */ - { - // total size: 0x2C - public: - class xAnimTransition* start; // offset 0x0, size 0x4 - class xAnimTransition* rise; // offset 0x4, size 0x4 - class xAnimTransition* fall; // offset 0x8, size 0x4 - class xAnimTransition* stop; // offset 0xC, size 0x4 - class xAnimTransition* dive_start; // offset 0x10, size 0x4 - class xAnimTransition* dive_stop; // offset 0x14, size 0x4 - class xAnimTransition* top_start; // offset 0x18, size 0x4 - class xAnimTransition* top_stop; // offset 0x1C, size 0x4 - class xAnimTransition* bottom_start; // offset 0x20, size 0x4 - class xAnimTransition* bottom_stop; // offset 0x24, size 0x4 - class xAnimTransition* hit; // offset 0x28, size 0x4 + U32 marker; + U32 set_view_angle; + F32 view_angle; + }; + + static struct + { + F32 bottom_anim_frac; + F32 top_anim_frac; + F32 bottom_anim_time; + F32 top_anim_time; + F32 hit_anim_time; + F32 damage_rot; + F32 death_time; + F32 vel_blur; + F32 fade_dist; + F32 player_radius; + F32 hook_fade_alpha; + F32 hook_fade_time; + struct + { + F32 edge_zone; + F32 sway; + F32 decay; + } horizontal; // offset 0x30, size 0xC + struct + { + F32 time; + F32 anim_out_time; + F32 min_dist; + F32 max_dist; + } dive; // offset 0x3C, size 0x10 + struct + { + F32 speed; + } camera; // offset 0x4C, size 0x4 + struct + { + F32 spring; + F32 decay; + } turn; // offset 0x50, size 0x8 + } fixed; + static struct + { + S32 flags; + class state_type* state; + class state_type* states[2]; + struct + { + xAnimTransition* start; + xAnimTransition* rise; + xAnimTransition* fall; + xAnimTransition* stop; + xAnimTransition* dive_start; + xAnimTransition* dive_stop; + xAnimTransition* top_start; + xAnimTransition* top_stop; + xAnimTransition* bottom_start; + xAnimTransition* bottom_stop; + xAnimTransition* hit; } anim_tran; // offset 0x10, size 0x2C - class hook_type* hook; // offset 0x3C, size 0x4 - class hook_type* hook_cache[8]; // offset 0x40, size 0x20 - class drop_asset* drop_cache[32]; // offset 0x60, size 0x80 - class xMarkerAsset* drop_marker_cache[32]; // offset 0xE0, size 0x80 - signed int hook_cache_size; // offset 0x160, size 0x4 - signed int drop_cache_size; // offset 0x164, size 0x4 - class xModelInstance* root_model; // offset 0x168, size 0x4 - class xModelInstance* ass_model; // offset 0x16C, size 0x4 - class xModelInstance* pants_model; // offset 0x170, size 0x4 - class xVec3 hook_loc; // offset 0x174, size 0xC - class xVec3 drop_loc; // offset 0x180, size 0xC - unsigned char drop_set_view_angle; // offset 0x18C, size 0x1 - float drop_view_angle; // offset 0x190, size 0x4 - float dismount_delay; // offset 0x194, size 0x4 - signed int anim_state; // offset 0x198, size 0x4 + class hook_type* hook; + class hook_type* hook_cache[8]; + drop_asset* drop_cache[32]; + xMarkerAsset* drop_marker_cache[32]; + S32 hook_cache_size; + S32 drop_cache_size; + xModelInstance* root_model; + xModelInstance* ass_model; + xModelInstance* pants_model; + xVec3 hook_loc; + xVec3 drop_loc; + bool drop_set_view_angle; + F32 drop_view_angle; + F32 dismount_delay; + S32 anim_state; } shared = { 1 }; // size: 0x19C, address: 0x4DF7E0 static F32 old_pants_clip_radius; @@ -175,7 +224,6 @@ namespace bungee_state { shared.pants_model->Flags &= 0xffdc; shared.pants_model->Flags |= 0x8; - // old_pants_clip_radius = shared.pants_model->Data->boundingSphere.radius; shared.pants_model->Data->boundingSphere.radius = old_pants_clip_radius; if (zGameExtras_CheatFlags() & 0x10000000) @@ -187,5 +235,484 @@ namespace bungee_state shared.ass_model->Flags &= ~0x3; } } + static void render_player(bool fade) + { + xShadowRender(&globals.player.ent, 100.0f); + xEntRender(&globals.player.ent); + + if (fade) + { + xFXRenderProximityFade(*shared.pants_model, 1.0f, fixed.fade_dist); + } + } + static void move_wedgie(const xVec3& stretch_loc) + { + if (shared.ass_model == NULL || shared.pants_model == NULL) + { + return; + } + shared.pants_model->Mat[2] = shared.root_model->Mat[2]; + + xMat4x3 tm; + xMat4x3 mworld; + xMat4x3 mlocal; + xMat4x3OrthoInv(&tm, (const xMat4x3*)shared.root_model->Mat); + xMat3x3Identity(&mworld); + mworld.pos = stretch_loc; + + static xVec3 tweak_cord_off = { 0 }; + static bool registered = false; + if (!registered) + { + registered = true; + xDebugAddTweak("Bungee|Hook|temp xoff", &tweak_cord_off.x, -10000.0f, 10000.0f, + NULL, NULL, 0); + xDebugAddTweak("Bungee|Hook|temp yoff", &tweak_cord_off.y, -10000.0f, 10000.0f, + NULL, NULL, 0); + xDebugAddTweak("Bungee|Hook|temp zoff", &tweak_cord_off.z, -10000.0f, 10000.0f, + NULL, NULL, 0); + } + mworld.pos += tweak_cord_off; + xMat4x3Mul(&mlocal, &mworld, &tm); + shared.pants_model->Mat[34] = *(RwMatrix*)&mlocal; + } + + static void update_hook_loc() + { + if (shared.hook == NULL || shared.hook->ent == NULL) + { + return; + } + + xVec3* hook_pos = xEntGetPos(shared.hook->ent); + shared.hook_loc = *hook_pos + shared.hook->asset->center; + } + + static bool find_drop_off() + { + S32 idx = -1; + F32 closest = SQR(shared.hook->asset->detach.dist); + for (S32 i = 0; i < shared.drop_cache_size; ++i) + { + xVec3 d = shared.drop_marker_cache[i]->pos - shared.hook_loc; + F32 len2 = d.length2(); + if (len2 >= closest) + { + continue; + } + idx = i; + closest = len2; + } + + if (idx != -1) + { + shared.drop_loc = shared.drop_marker_cache[idx]->pos; + shared.drop_set_view_angle = shared.drop_cache[idx]->set_view_angle; + shared.drop_view_angle = shared.drop_cache[idx]->view_angle; + return true; + } + return false; + } + static void trigger(U32 toEvent) + { + zEntEvent(shared.hook, shared.hook, toEvent); + } + + enum state_enum + { + STATE_INVALID = -1, + BEGIN_STATE = 0, + STATE_ATTACHING = 0, + STATE_HANGING = 1, + END_STATE = 2, + MAX_STATE = 2, + }; + class state_type + { + // total size: 0x8 + public: + enum state_enum type; // offset 0x0, size 0x4 + + virtual void need_vtable(); // FIXME: fake func + }; + class ent_info + { + // total size: 0x8 + public: + class xEnt* ent; // offset 0x0, size 0x4 + signed int hits; // offset 0x4, size 0x4 + }; + class env_info + { + // total size: 0xC + public: + class xEnv* env; // offset 0x0, size 0x4 + unsigned char collide; // offset 0x4, size 0x1 + signed int hits; // offset 0x8, size 0x4 + }; + class hanging_state_type : public state_type + { + public: + xVec3 loc; + xVec3 vel; + xVec3 last_loc; + xVec3 last_hook_loc; + xVec3 cam_loc; + xVec3 cam_vel; + xVec3 cam_dir; + xVec3 cam_dir_vel; + F32 dive_remaining; + F32 rot; + F32 rot_vel; + xVec2 stick_loc; + F32 stick_ang; + F32 stick_mag; + F32 stick_frac; + xVec3 collide_accel; + F32 roll_offset; + bool detaching; + xVec3 drop_off_vel; + F32 max_yvel; + bool dying; + F32 control_lag_timer; + F32 control_lag_max; + bool has_dived; + bool can_dive; + U32 last_health; + struct + { + F32 time; + F32 end_time; + xVec3 start_loc; + xVec3 end_loc; + xQuat start_dir; + xQuat end_dir; + } detach; // offset 0xC0, size 0x40 + xModelInstance* root_model; + xModelInstance* ass_model; + xModelInstance* pants_model; + hook_asset h; + struct + { + struct + { + float rest_dist; + float emax; + float spring; + float alpha; + float omega; + } vertical; // offset 0x0, size 0x14 + struct + { + float vscale; + float hscale; + float roll_decay; + } camera; // offset 0x14, size 0xC + } eh; // offset 0x198, size 0x20 + ent_info ent_cache[256]; + S32 ent_cache_size; + env_info env_cache; + + static void on_tweak_collision(const tweak_info& ti); + void reset_props_collision(); + static void on_tweak_camera(const tweak_info& ti); + void reset_props_camera(); + static void on_tweak_horizontal(const tweak_info& ti); + void reset_props_horizontal(); + static void on_tweak_vertical(const tweak_info& ti); + void reset_props_vertical(); + + F32 spring_velocity(F32 x, F32 v, F32 e, F32 k, F32 g, F32 xc) const; + F32 spring_potential_energy(F32 x, F32 k, F32 g, F32 xc) const; + F32 spring_potential_energy(F32, F32) const; + F32 kinetic_energy(F32 v) const; + F32 find_spring_min(F32 min_dist, F32 max_dist, F32 gravity, F32 damp) const; + + F32 spring_energy(F32 x, F32 v, F32 k, F32 g, F32 xc) const; + }; + void hanging_state_type::on_tweak_collision(const tweak_info& ti) + { + reinterpret_cast(ti.context)->reset_props_collision(); + } + void hanging_state_type::reset_props_collision() + { + if (shared.hook == NULL) + { + return; + } + h.collision = shared.hook->asset->collision; + + if (h.collision.damage_velocity == 0.0f) + { + h.collision.damage_velocity = FLOAT_MIN; + } + else + { + h.collision.damage_velocity *= max_yvel; + } + + if (h.collision.hit_velocity == 0.0f) + { + h.collision.hit_velocity = FLOAT_MIN; + } + else + { + h.collision.hit_velocity *= max_yvel; + } + } + void hanging_state_type::on_tweak_camera(const tweak_info& ti) + { + reinterpret_cast(ti.context)->reset_props_camera(); + } + void hanging_state_type::reset_props_camera() + { + if (shared.hook == NULL) + { + return; + } + h.camera = shared.hook->asset->camera; + + h.camera.vel_scale /= max_yvel; + h.camera.view_angle *= DEG2RAD(1.0f); + h.camera.offset_dir *= DEG2RAD(1.0f); + h.camera.offset_dir -= h.camera.view_angle; + eh.camera.roll_decay = 1.0f - h.camera.roll_speed; + } + void hanging_state_type::on_tweak_horizontal(const tweak_info& ti) + { + reinterpret_cast(ti.context)->reset_props_horizontal(); + } + void hanging_state_type::reset_props_horizontal() + { + if (shared.hook == NULL) + { + return; + } + h.horizontal = shared.hook->asset->horizontal; + } + void hanging_state_type::on_tweak_vertical(const tweak_info& ti) + { + reinterpret_cast(ti.context)->reset_props_horizontal(); + } + void hanging_state_type::reset_props_vertical() + { + if (shared.hook == NULL) + { + return; + } + h.vertical = shared.hook->asset->vertical; + + h.vertical.gravity *= -1.0f * h.vertical.frequency * h.vertical.frequency; + h.vertical.dive *= h.vertical.gravity; + h.vertical.damp = range_limit(h.vertical.damp, 0.0f, 1.0f); + h.vertical.min_dist *= -1.0f; + h.vertical.max_dist *= -1.0f; + h.vertical.min_dist = find_spring_min(h.vertical.min_dist, h.vertical.max_dist, + h.vertical.gravity, h.vertical.damp); + eh.vertical.rest_dist = 0.5f * (h.vertical.max_dist + h.vertical.min_dist); + eh.vertical.spring = h.vertical.gravity / eh.vertical.rest_dist; + eh.vertical.alpha = -h.vertical.damp * xsqrt(eh.vertical.spring); + eh.vertical.omega = xsqrt(eh.vertical.spring - eh.vertical.alpha * eh.vertical.alpha); + eh.vertical.emax = spring_energy(h.vertical.max_dist, 0.0f, eh.vertical.spring, + h.vertical.gravity, eh.vertical.rest_dist); + max_yvel = + spring_velocity(eh.vertical.rest_dist, 1.0f, eh.vertical.emax, eh.vertical.spring, + h.vertical.gravity, eh.vertical.rest_dist); + h.camera.vel_scale = shared.hook->asset->camera.vel_scale / max_yvel; + } + + F32 hanging_state_type::spring_velocity(F32 x, F32 v, F32 e, F32 k, F32 g, F32 xc) const + { + F32 ret = e - spring_potential_energy(x, k, g, xc); + if (ret <= 0.0f) + { + return 0.0f; + } + ret = xsqrt(2.0f * ret); + + if (v < 0.0f) + { + if (ret > 0.0f) + { + return -ret; + } + } + else + { + if (ret < 0.0f) + { + return -ret; + } + } + return ret; + } + F32 hanging_state_type::spring_potential_energy(F32 x, F32 k, F32 g, F32 xc) const + { + return -(g * -(0.5f * xc - x) - spring_potential_energy(x, k)); + } + F32 hanging_state_type::spring_potential_energy(F32 x, F32 k) const + { + return 0.5f * k * x * x; + } + F32 hanging_state_type::spring_energy(F32 x, F32 v, F32 k, F32 g, F32 xc) const + { + return kinetic_energy(v) + spring_potential_energy(x, k, g, xc); + } + F32 hanging_state_type::kinetic_energy(F32 v) const + { + return 0.5f * v * v; + } + F32 hanging_state_type::find_spring_min(F32 min_dist, F32 max_dist, F32 gravity, + F32 damp) const + { + F32 e = xexp(-PI * damp * xsqrt(-(damp * damp - 1.0f))); + return (2.0f * min_dist + max_dist * (e - 1.0f)) / (1.0f + e); + } + U32 check_anim_start(xAnimTransition*, xAnimSingle*, void*) + { + return 0; + } + U32 check_anim_hit_to_dive(xAnimTransition*, xAnimSingle*, void*) + { + shared.anim_state &= ~0x40; + return shared.anim_state & 0x2 && (shared.anim_state & 0x80) == 0; + } + U32 check_anim_hit_to_top(xAnimTransition*, xAnimSingle*, void*) + { + shared.anim_state &= ~0x40; + return shared.anim_state & 0x8 && (shared.anim_state & 0x80) == 0; + } + U32 check_anim_hit_to_bottom(xAnimTransition*, xAnimSingle*, void*) + { + shared.anim_state &= ~0x40; + return shared.anim_state & 0x20 && (shared.anim_state & 0x80) == 0; + } + U32 check_anim_hit_to_cycle(xAnimTransition*, xAnimSingle*, void*) + { + shared.anim_state &= ~0x40; + return (shared.anim_state & 0x2a) == 0 && (shared.anim_state & 0x80) == 0; + } + U32 check_anim_hit_to_death(xAnimTransition*, xAnimSingle*, void*) + { + shared.anim_state &= ~0x40; + if (shared.anim_state & 0x80) + { + play_sound(SOUND_DEATH, 1.0f); + return 1; + } + return 0; + } + static S32 find_nearest_hook(const xVec3& loc) + { + S32 found = -1; + F32 closest = 10000000000.0f; + for (S32 i = 0; i < shared.hook_cache_size; ++i) + { + F32 attach_dist = shared.hook_cache[i]->asset->attach.dist; + xVec3* p = xEntGetPos(shared.hook_cache[i]->ent); + xVec3 dloc = *p + shared.hook_cache[i]->asset->center - loc; + F32 len2 = dloc.length2(); + if (len2 <= SQR(attach_dist) && len2 < closest) + { + found = i; + closest = len2; + } + } + return found; + } + static void init_sounds() + { + } + static xModelInstance* get_hook_model() + { + if (shared.hook == NULL || shared.hook->ent == NULL) + { + return NULL; + } + return shared.hook->ent->model; + } + static void fade_hook_reset() + { + if ((shared.flags & 0x60) == 0) + { + return; + } + + shared.flags &= ~0x60; + xModelInstance* hook = get_hook_model(); + if (hook != NULL) + { + hook->Alpha = 1.0f; + hook->Flags &= 0xbfff; + hook->PipeFlags &= ~0x30; + } + } + static void fade_hook_out() + { + if (shared.flags & 0x40) + { + return; + } + + shared.flags &= ~0x60; + xModelInstance* hook = get_hook_model(); + if (hook != NULL) + { + hook->Flags |= 0x4000; + hook->PipeFlags = hook->PipeFlags & ~0x30 | 0x30; + shared.flags |= 0x40; + } + } + static void fade_hook_in() + { + if (shared.flags & 0x20) + { + return; + } + + shared.flags &= ~0x60; + xModelInstance* hook = get_hook_model(); + if (hook != NULL) + { + hook->Flags |= 0x4000; + hook->PipeFlags = hook->PipeFlags & ~0x30 | 0x30; + shared.flags |= 0x20; + } + } + static void fade_hook_update(float dt) + { + if ((shared.flags & 0x60) == 0) + { + return; + } + + xModelInstance* hook = get_hook_model(); + if (hook == NULL) + { + return; + } + + float vel = (1.0f - fixed.hook_fade_alpha) / fixed.hook_fade_time; + if (shared.flags & 0x40) + { + hook->Alpha = -(vel * dt - hook->Alpha); + if (hook->Alpha <= fixed.hook_fade_alpha) + { + hook->Alpha = fixed.hook_fade_alpha; + shared.flags &= ~0x40; + } + } + else + { + hook->Alpha = vel * dt + hook->Alpha; + if (hook->Alpha >= 1.0f) + { + hook->Alpha = 1.0f; + shared.flags &= ~0x20; + hook->Flags &= 0xbfff; + hook->PipeFlags &= ~0x30; + } + } + } } // namespace } // namespace bungee_state diff --git a/src/SB/Game/zFX.h b/src/SB/Game/zFX.h index 304820085..3918de9a5 100644 --- a/src/SB/Game/zFX.h +++ b/src/SB/Game/zFX.h @@ -8,6 +8,9 @@ #include #include +struct tweak_info; +struct tweak_callback; + enum zFXGooState { zFXGooStateNormal, @@ -41,88 +44,6 @@ struct zFXGooInstance xVec3 pos_parentOnFreeze; }; -struct tweak_callback; - -struct uint_data -{ - U32 value_def; - U32 value_min; - U32 value_max; -}; - -struct float_data -{ - F32 value_def; - F32 value_min; - F32 value_max; -}; - -struct bool_data -{ - U8 value_def; -}; - -struct select_data -{ - U32 value_def; - U32 labels_size; - char** labels; - void* values; -}; - -struct flag_data -{ - U32 value_def; - U32 mask; -}; - -struct raw_data -{ - U8 pad[16]; -}; - -struct int_data -{ - S32 value_def; - S32 value_min; - S32 value_max; -}; - -struct tweak_info -{ - substr name; - void* value; - tweak_callback* cb; - void* context; - U8 type; - U8 value_size; - U16 flags; - union - { - int_data int_context; - uint_data uint_context; - float_data float_context; - bool_data bool_context; - select_data select_context; - flag_data flag_context; - raw_data all_context; - }; -}; - -struct tweak_callback -{ - void (*on_change)(tweak_info&); - void (*on_select)(tweak_info&); - void (*on_unselect)(tweak_info&); - void (*on_start_edit)(tweak_info&); - void (*on_stop_edit)(tweak_info&); - void (*on_expand)(tweak_info&); - void (*on_collapse)(tweak_info&); - void (*on_update)(tweak_info&); - void (*convert_mem_to_tweak)(tweak_info&, void*); - void (*convert_tweak_to_mem)(tweak_info&, void*); -}; - extern U32 gFXSurfaceFlags; void on_spawn_bubble_wall(const tweak_info& tweak); diff --git a/src/SB/Game/zNPCTypeBossPatrick.cpp b/src/SB/Game/zNPCTypeBossPatrick.cpp index 86759b338..e31136bda 100644 --- a/src/SB/Game/zNPCTypeBossPatrick.cpp +++ b/src/SB/Game/zNPCTypeBossPatrick.cpp @@ -4,6 +4,7 @@ #include "iModel.h" #include "xCollide.h" +#include "xDebug.h" #include "xMath.h" #include "xMath3.h" #include "xstransvc.h" diff --git a/src/SB/Game/zNPCTypePrawn.cpp b/src/SB/Game/zNPCTypePrawn.cpp index 0c1643e6a..274548844 100644 --- a/src/SB/Game/zNPCTypePrawn.cpp +++ b/src/SB/Game/zNPCTypePrawn.cpp @@ -1,5 +1,7 @@ #include "zNPCTypePrawn.h" +#include "xDebug.h" + #include #define f1052 1.0f