commit d3ada59252eb8e665a09fd7255001e639e51b402 Author: Kevinmonitor Date: Thu Jan 26 18:34:56 2023 +0700 commit 1 diff --git a/LogWindow.dat b/LogWindow.dat new file mode 100644 index 0000000..c5f5451 Binary files /dev/null and b/LogWindow.dat differ diff --git a/READ THIS TO BECOME THE STRONGEST.txt b/READ THIS TO BECOME THE STRONGEST.txt new file mode 100644 index 0000000..2ebac4f --- /dev/null +++ b/READ THIS TO BECOME THE STRONGEST.txt @@ -0,0 +1 @@ +test manual \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..774abf3 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# NarumiSTG + vidya games diff --git a/config.dat b/config.dat new file mode 100644 index 0000000..cd6f2ab Binary files /dev/null and b/config.dat differ diff --git a/config_ph3sx.exe b/config_ph3sx.exe new file mode 100644 index 0000000..6c68259 Binary files /dev/null and b/config_ph3sx.exe differ diff --git a/docs/Change Log.txt b/docs/Change Log.txt new file mode 100644 index 0000000..74fc718 --- /dev/null +++ b/docs/Change Log.txt @@ -0,0 +1,550 @@ +A mostly-complete history log of engine updates can be found here. + +1.32b + Changes: + - All functions and actions that change a shot's graphic ID has an additional feature: + - The actual graphic ID will be the absolute value of the value received. + - If the value received was negative, the graphic change operation will preserve the shot's previous spin angular velocity and Z-angle. + - Affected functions and actions: + - ObjShot_SetGraphic + - ObjMove_AddPatternA3 + - ObjMove_AddPatternA4 + - ObjMove_AddPatternB3 + - ObjMove_AddPatternC3 + - ObjMove_AddPatternC4 + - TRANSFORM_GRAPHIC_CHANGE + Additions: + - Added an instruction on how to get ph3sx to work with Wine. (Check readme.txt) + - Added SetIntersectionVisualizationRenderPriority. + Bug fixes: + - Fixed incorrect documentation for some functions. + - Fixed AddPoint not working correctly. + - Fixed some issues with acceleration and max speed when converting from B-movement to A-movement or C-movement with AddPattern. + +1.32a + Changes: + - Renamed "real" to "float". + - r (number suffix) -> f (number suffix) + - 45.22r -> 45.22f + - real -> float + - as_real -> as_float + - as_real_array -> as_float_array + - VAR_REAL -> VAR_FLOAT + - Changed how setting curvy laser node widths work. Instead of directly setting the width, the functions will set the nodes' width scales. + - Renamed ObjCrLaser_SetNodeWidth to ObjCrLaser_SetNodeWidthScale. + - Renamed ObjCrLaser_GetNodeWidth to ObjCrLaser_GetNodeWidthScale. + - Improved cross-compatibility between different movement types of the following functions: + - ObjMove_SetSpeed + - ObjMove_SetAngle + - ObjMove_SetAcceleration + - ObjMove_SetMaxSpeed + - ObjMove_SetAngularVelocity + - Swapped the "shot graphic ID" and "target ID" arguments in ObjMove_AddPatternA4. + - Swapped the "max speed" and "angular velocity" arguments of the following functions: + - ObjMove_AddPatternA2 + - ObjMove_AddPatternA3 + - ObjMove_AddPatternA4 + - TRANSFORM_ADDPATTERN_A2 in ObjPatternShot transforms + - Completely removed shot scripts. + - Moved SetShotDeleteEventEnable to the stage script. + - Default values for all three delete events are true. + - Furthermore, fixed EV_DELETE_SHOT_IMMEDIATE and EV_DELETE_SHOT_FADE not being notified properly. + - Restructed event arguments of EV_DELETE_SHOT_TO_ITEM. + - The third event argument; "player collision", has been removed. + - Collision with the player will now trigger EV_DELETE_SHOT_IMMEDIATE instead of EV_DELETE_SHOT_TO_ITEM. + - Increased the minimum width for straight and curve lasers, primarily for delay visibility purposes. (Thanks to Naudiz) + - Allowed lasers to lose penetration (life) points. (Thanks to Naudiz) + - Like with any shot object, this will only occur when a laser lacks spell resistance (which it has by default). + - Removed #BGM. + - Made it so that the window sizes list will be autogenerated instead of defaulting to [640x480, 800x600, 960x720, 1280x960] when window.size.list in th_dnh.def doesn't exist. + - Size multipliers are [x1, x1.25, x1.5, x2], with screen.width and screen.height being the base resolution. + - Made it so that the engine will check for the required .dll modules during initialization. + - d3d9.dll + - d3dx9_43.dll + - d3dcompiler_43.dll + - dinput8.dll + - dsound.dll + - In the event where the Direct3D device enters a lost state, the engine will now attempt to restore up to 60 times before throwing an error, rather than only once. + - Removed ObjItem_SetAutoCollectEnable, and replaced it with ObjItem_SetAutoCollectEnableFlags. + Additions: + - Added Interpolate_X_Array, Interpolate_X_Angle, and Interpolate_X_AngleR. (Thanks to Naudiz) + - Added ObjShot_SetEnemyIntersectionInvalidFrame and ObjShot_SetPenetrateShotEnable. (Thanks to Naudiz) + - Added SetShotTextureFilter, SetItemTextureFilter, ObjRender_SetTextureFilter, and ObjShot_SetAngleRounding. (Thanks to Naudiz) + - Added SetEnemyAutoDeleteClip, ObjEnemy_SetAutoDelete, and ObjEnemy_SetDeleteFrame. (Thanks to NicholasLogan) + - Added ObjMove_SetAngularAcceleration, ObjMove_SetAngularMaxVelocity, and ObjMove_AddPatternA5. (Thanks to NicholasLogan) + - Added an overload to CreateShotA2, adding an angular velocity argument in between the acceleration and max speed ones. (Thanks to Naudiz) + - Added ObjMove_GetMovementType. (Thanks to Naudiz) + - Added constants: + - MOVE_NONE + - MOVE_ANGLE + - MOVE_XY + - MOVE_XY_ANGLE + - MOVE_LINE + - Added the C-movement type for ObjMove. (Thanks to Naudiz) + - CreateShotC1 + - CreateShotC2 + - CreateShotOC1 + - ObjMove_AddPatternC1 + - ObjMove_AddPatternC2 + - ObjMove_AddPatternC3 + - Added AddPattern functions for line-movement. (Thanks to Naudiz) + - ObjMove_AddPatternD1 (AddPattern version of ObjMove_SetDestAtSpeed) + - ObjMove_AddPatternD2 (AddPattern version of ObjMove_SetDestAtFrame) + - ObjMove_AddPatternD3 (AddPattern version of ObjMove_SetDestAtWeight) + - Added ObjMove_CancelMovement. + - Added new transformations to pattern shot objects. (Thanks to Naudiz) + - TRANSFORM_ADDPATTERN_C1 + - TRANSFORM_ADDPATTERN_C2 + - Added psrand. + - Added array overloads to the following functions: + - ObjSprite2D_SetSourceRect + - ObjSprite2D_SetDestRect + - ObjSpriteList2D_SetSourceRect + - ObjSpriteList2D_SetDestRect + - ObjSprite3D_SetSourceRect + - ObjSprite3D_SetDestRect + - ObjSprite3D_SetSourceDestRect + - Added support for hexadecimal numbers in text color tags. + - "[f tc=0xffffff]" is equivalent to "[f tc=(255,255,255)]". + - Added GetWorkingDirectory. + - Added an option to allow the engine to keep running while the window is unfocused. (Thanks to Naudiz) + - Added SetEnableUnfocusedProcessing and IsWindowFocused. + - Added the property "unfocused.processing" to th_dnh.def. + - Added EV_APP_LOSE_FOCUS and EV_APP_RESTORE_FOCUS. + - Added exponent format for numbers. + - "5.462e3" or "-231.9e-2" are now valid numbers. + - Added ObjItem_SetAutoCollectEnableFlags. + - ITEM_AUTOCOLLECT_PLAYER_SCOPE + - ITEM_AUTOCOLLECT_COLLECT_ALL + - ITEM_AUTOCOLLECT_POC_LINE + - ITEM_AUTOCOLLECT_COLLECT_CIRCLE + - ITEM_AUTOCOLLECT_ALL + - Added an overload to atoi. + - Added SetScore, SetGraze, and SetPoint. + Bug fixes: + - Fixed .dat archives not working. + - Fixed incorrect null checks, resulting in the game crashing when trying to operate on a null value. + - For example, using Obj_GetValue on a non-existent key will yield a null value. + - Fixed a crash bug which may sometimes happen when trying to parse a script file that ends with a line comment. + - Fixed ObjMove_AddPatternXX's shot graphic change not working with loose and curvy lasers. + - Fixed SetShotIntersectionCircle/Line not registering intersection, despite showing up in intersection visualization. + +1.31b + Bug fixes: + - Fixed a bug where the game would freeze when compiling a script with a syntax error. + - Fixed a minor visual bug where the LogWindow's sub-info fields would all try to display over each other on initialization. + +1.31a + Changes: + - This version breaks replay, common data, and .dat archive backwards compatibility. + - Replaced the default script select backgrounds with a radder version. (Thanks to Naudiz) + - Renamed GetShotIdAll to GetAllShotID. + - Changed the text representation of script value types in error messages. + - "real-array-array" -> "real[][]" + - Script matrix functions can now take in a 4x4 array instead of only a 1x16 array previously. + - The element type is also no longer limited to real. + - Made setting ObjRender_SetEnableDefaultTransformMatrix to false still load the camera matrix. + - Allowed multiple ObjSounds to independently stream the same sound file. + - Shortened the module directory in Log messages of the LogWindow to "../". + - Removed the behaviour where the 2D and 3D camera resets upon transitioning from the package scene to the stage scene. + - Fog data is no longer split between package-level and stage-level scripts. + - The default FPS counter no longer briefly appears when starting with package.script.main. + - Maximizing the window now triggers fullscreen mode. + - Objects now have separate tables each for string-indexed and int-indexed. + - Improved support for particle list objects for older PCs. + - Made it so that curvy lasers can be shortened. (Thanks to Naudiz) + - ObjFileT_SplitLineText now splits from pattern rather than from a list of delimiters. + - Reduced the float truncation epsilon. (0.01 -> 0.000001) + - #include in shader source files now behaves like regular script includes. + - Normal shot objects can now have multiple hitboxes again. + - Change loose and curvy lasers behaviour when delay motion is enabled. (Thanks to Naudiz) + - Text objects can now be centered around their object positions. No need to use ObjText_SetMaxWidth for that anymore. (Thanks to Naudiz) + Additions: + - Added missing function documentation for GetAllEnemyID. + - Added an overload each for Rotate2D and Rotate3D, taking in the rotation origin point. + - Expanded the variety of intersection-checking functions: + - IsIntersected_Point_Polygon + - IsIntersected_Point_Circle + - IsIntersected_Point_Ellipse + - IsIntersected_Point_Line + - IsIntersected_Point_RegularPolygon + - IsIntersected_Circle_Polygon + - IsIntersected_Circle_Circle + - IsIntersected_Circle_Ellipse + - IsIntersected_Circle_RegularPolygon + - IsIntersected_Line_Polygon + - IsIntersected_Line_Circle + - IsIntersected_Line_Ellipse + - IsIntersected_Line_Line + - IsIntersected_Line_RegularPolygon + - IsIntersected_Polygon_Polygon + - IsIntersected_Polygon_Ellipse + - IsIntersected_Polygon_RegularPolygon + - Added ReflectAngle and ReflectAngleR. (Thanks to Naudiz) + - Added Python-style reverse indexing of arrays. (Thanks to Naudiz) + - See "New Scripting Features". + - arr[-n] is equivalent to arr[length(arr) - n] + - Also works in erase and insert. + - Added replace and remove. (Thanks to Naudiz) + - #ifdef, #ifndef, #else, and #endif preprocessor directives for scripts. + - Several script macros were added: + - _DNH_PH3SX_ + - SCRIPT_PACKAGE (defined in package-level scripts) + - SCRIPT_STAGE (defined in stage-level scripts) + - #define is not yet supported. + - Added ObjItem_GetIntersectionEnable. (Thanks to Naudiz) + - Added ObjRender_GetColorHex, ObjPrim_GetVertexColorHex, and ObjCrLaser_GetNodeColorHex. (Thanks to Naudiz) + - Added ColorHexRGBtoHSV. + - Added another event argument to EV_DELETE_SHOT_PLAYER. + - Added a "Sound Memory" display to the Sound tab of the LogWindow. + - Added INFO_IS_REQUIRE_ALL_DOWN to ObjEnemyBossScene_GetInfo. (Thanks to Naudiz) + - Added ObjEnemy_SetMaximumDamage and ObjEnemy_AddLifeEx. + - Added INFO_DAMAGE_PREVIOUS_FRAME to ObjEnemy_GetInfo. + - Added ObjText_SetFixedWidth. + - Added ObjText_GetText. (Thanks to Naudiz) + - Added ObjText_SetVerticalAlignment. (Thanks to Naudiz) + - Added ObjCrLaser_SetTipCapping, ObjCrLaser_GetNodeRenderWidth, and ObjCrLaser_SetNodeRenderWidth. (Thanks to Naudiz) + - Added overloads to ObjCrLaser_SetNode and ObjCrLaser_AddNode. (Thanks to Naudiz) + - Added ObjShot_SetFixedAngle and ObjShot_SetDelayAngularVelocity. (Thanks to Naudiz) + - Added SplitString2. + - Added Obj_GetValueCount and Obj_GetValueCountI. + - Added a progress bar to the FileArchiver. + - Added an overload to SetStgFrame. (Thanks to Naudiz) + - Added GetConfigVirtualKeyMapping and GetVirtualKeyMapping. (Thanks to Naudiz) + Bug fixes: + - Fixed incorrect documentation of IsIntersected_Circle_RegularPolygon. + - Fixed the Y shot intersection scale not functioning properly on loose lasers. + - Fixed the engine crashing upon trying to parse an excess comma in function parameter lists. + - Fixed type-checking bugs with array-index-assignment operations. + - Fixed an issue where the parser would indefinitely hang upon trying to parse an ill-formed for-loop. + - Fixed a bug where .wav files over 1MB large would get cut off at the end. + - Fixed a bug where multiple streaming ObjSounds playing the same file would not function correctly. + - Fixed ObjSound_IsPlaying returning false if called in the same frame of ObjSound_Play. + - Fixed a bug where shot objects colliding with the player gets deleted before EV_HIT is notified. + - Fixed GetShotIdInCircleA1 incorrectly returning player shot IDs instead of enemy shot IDs. + - Fixed ObjShot_Regist in a player script returning null if IsPermitPlayerShot is true. + - Fixed a bug where the shot object colliding with the player is deleted before the notification of EV_HIT. + - Fixed off-centered shot and item graphics. + - Fixed the game crashing upon trying to parse an ill-formed argument list in user shot/item data files. + - Fixed a bug where 3D render objects drawn below the min STG frame render priority would get abnormally stretched out. + - Fixed ObjMove_GetSpeedX/Y returning incorrect values for ObjMove_SetDestAtXXX functions. + - Fixed the game crashing when setting ObjRender_SetEnableDefaultTransformMatrix to false for 3D objects. + - Fixed incorrect conversion of A-movement to B-movement for ObjMove. + - Fixed CreateItemU1/2 causing the created item to render at (0, 0) for a single frame. (Thanks to Naudiz) + - Fixed ObjMove_AddPatternXX not working on move objects that do not have an existing movement pattern. (Thanks to Naudiz) + - Fixed a rare bug with array initialization. + - Fixed a bug where ObjShot_SetPenetration(obj, 0) would not notify EV_DELETE_SHOT_PLAYER. + - Fixed a rare crash during enemy boss scene loading. + - Fixed a bug where the game would freeze when trying to restart the stage scene in a package script while an enemy boss scene hasn't finished loading. + - Fixed a rare crash with script object deletion. + +1.30a: + Changes: + - Greatly improved the speed of the script code interpreter. + - Made the maximum sizes of render targets respect the Direct3D device capabilities. + - EV_REQUEST_LIFE now accepts all types of values (will be converted to reals). + - In case that an array was passed (multiple bosses), each elements will also be converted to reals. + - Direct3D device capabilities will now be checked at the start, and the user will be notified if they are insufficient to run the engine. + - Changed the default render priority of items to 40. (Previously 60, what the fuck mkm) + - Changed the behaviour of resource pre-loading. (LoadTexture, LoadMesh, etc.) + - Loaded resources are no longer script-dependent, they will remain loaded even if the script that loaded them has been closed. + - Changed the arguments of ObjPatternShot_AddTransform/ObjPatternShot_SetTransform. + - Additionally, the above two functions now take in varargs. + - Improved GetObjectDistance. + - Introduced the ability to use StartScript a second time without having to use LoadScript again. + - Renamed ObjSound_SetRestartEnable to ObjSound_SetResumeEnable. + - Usage unchanged. + - Rearranged the arguments of ObjPatternShot_Add/SetTransform. + - ObjFile_Store now use the source file's original line endings. + - Binary, octal, and hexadecimal number literals now default to int. + - Changed the usage of the function "resize". + - Improved the speed of boss scene scripts loading. + Additions: + - Many new additions to the scripting language. + - See "New Scripting Features". + - Added GetObjectDistanceSq and GetObjectDeltaAngle. + - Added an overload each for GetCommonData and GetAreaCommonData. + - Added GetSystemTimeMilliS and GetSystemTimeNanoS. + - Added SetInvalidPositionReturn, a function for changing the "invalid position" from (0, 0). + - Added functions for pointer-based common data access: + - LoadCommonDataValuePointer + - LoadAreaCommonDataValuePointer + - IsValidCommonDataValuePointer + - SetCommonDataPtr + - GetCommonDataPtr + - Added IsVertexShaderSupported. + - Added the ability to set the read offset of .dat archives. + - Added new ObjPatternShot transforms: + - TRANSFORM_ADDPATTERN_B1 + - TRANSFORM_ADDPATTERN_B2 + - Renamed TRANSFORM_ADDPATTERNA1 to TRANSFORM_ADDPATTERN_A1 + - Renamed TRANSFORM_ADDPATTERNA2 to TRANSFORM_ADDPATTERN_A2 + - Added new ObjPatternShot patterns: (thanks to Naudiz) + - PATTERN_LINE + - PATTERN_ROSE + - Added back in script source caching, plus the ability to remove a script from the cache. + - Added ObjEnemyBossScene_SetUnloadCache. + - Added a "Cached Scripts" panel to the Script tab of the LogWindow. + - Added a "CPU Time" column to the Script tab of the LogWindow. + - Added a "Shader" tab to the LogWindow. + - Added an overload for ColorARGBToHex. + - Added ObjItem_SetPositionRounding. + - Added new maths functions: + - log2 + - logn + - erf + - gamma + - distance + - distancesq + - dottheta + - rdottheta + - cbrt + - AngularDistance + - AngularDistanceR + - Rotate2D + - Rotate3D + - Added count_rand, count_prand, reset_count_rand, and reset_count_prand. + - Added Interpolate_X and Interpolate_X_PackedInt. + - Added GetScriptStatus. + - STATUS_LOADING + - STATUS_LOADED + - STATUS_RUNNING + - STATUS_PAUSED + - STATUS_CLOSING + - STATUS_INVALID + - Added implicit array casting for initialization, assignment, and concatenation. + - Only applicable for int[] <-> real[] <-> null + - Added array casting functions: + - as_int_array + - as_real_array + - as_bool_array + - as_char_array + - as_x_array + - Added StringFormat, a string formatting function in the style of C's sprintf. + - Added IsIntersected_Circle_RegularPolygon and IsIntersected_Circle_Ellipse. + - Added new array functions: contains, insert. + - Added ObjRender_SetEnableDefaultTransformMatrix. + - Added ObjPrim_GetTexture. + Bug fixes: + - Fixed LoadMesh crashing the engine. + - Fixed ObjCol_GetListOfIntersectedShotID incorrectly expecting only 1 argument. + - Fixed a bug where whitespaces in parameter lists in text object tags are incorrectly parsed. + - Fixed a bug where the "Show LogWindow" option would disappear if the game was set to start in (borderless) fullscreen mode. + - Fixed the sound streamer behaving incorrectly when playing a .wav file larger than 1MB a second time. + - Fixed a bug where ObjSound_Seek would be ineffectual if used when the sound isn't playing or within 2 frames after being played. + - Fixed the Y hitbox scale not affecting the hitboxes of laser objects. + - Fixed the LogWindow not able to output logs to file. + - Fixed a bug where penetrating player shots may randomly not correctly collide with enemy hitboxes and mess up replays. + - Fixed the engine crashing if the stage scene is quit and there is an ObjPatternShot, whose parent is a dead boss object, that wasn't manually deleted. + - Fixed the LogWindow's Log tab not horizontally scrolling the newest line into view. + - Fixed a bug with the remainder operation where using (kn % -n) or (-kn % n) where (k) is an integer results in (-n). + - Fixed crash bugs with ternary statements in the following cases: + - let a = [condition ? 0 : 1]; + - a[condition ? 0 : 1] = 100; + - Fixed a package crash that happens when LoadScriptInLoadThread loads a stage script that contains a parser error. + - Fixed a bug that made variable-overshadowing a function throw a parser error. + - let power = 100; //This is possible again. + - Fixed a bug where an ObjMove would lag for one frame after applying its last AddPattern transform. + - Fixed a "feature" where a multidimensional array can host values of different types. + - Fixed a bug where Windows' list-searching feature was interfering with key remapping in the config. + - Fixed a bug where empty lines in text file object are skipped over in some devices. + - Fixed ObjFileT_SplitLineText having an incorrect return value if the object is invalid. + - Fixed an issue where the engine's default 3D render shader and 3D particle list shader don't work on AMD graphics cards. + - Also updated the shader source files in the sample scripts with this fix. + - Fixed a null pointer read crash bug during engine initialization. + - Fixed a bug where short-circuited logical expressions would not convert to boolean. + +1.21a: + - Fixed MatrixMultiply and MatrixDivide functioning incorrectly. + - Added MatrixTransformVector for transforming a Vector3 by a transformation matrix. + - Added a hex overload for SetFogParam. + - Added a floored division operation. ("~/" and "~/=") + - Added "resize", a function for resizing arrays. + - Modified the functionality of the array slice operation and operator. + - Upper slice bound is automatically capped at the array's size. + - More options for text object tags. + - Increased the smoothness of rendered fonts. + - Fixed SetShotIntersectionCircle and SetShotIntersectionLine not working. + - Fixed a memory leak issue that was causing the "too many open files" error message. + - Using ObjRender_SetAlpha on a 2D sprite list object whose vertices were closed will now have an alpha-multiply effect. + - Optimizations. + +1.20b: + - Fixed a bug that caused for loops using new variables to not function correctly. + - Fixed a bug that caused all GetColor functions to return incorrect values. (Including GetShotDataInfoA1) + - Fixed a bug where off-centered player hitboxes would behave strangely. + - Fixed the game crashing on script end/retry. (How the fuck did I not notice this before 1.20a release bloody hell) + - Added ObjShot_SetSpinAngularVelocity. + +1.20a: + - Reworked some math calculations. SIMD instructions are utilized. + - A legacy version will also be provided in case your CPU do not support vectorization. + - The vectorized version requires the following instruction sets: + - SSE + - SSE2 + - SSE3 + - SSE4.1 + - Generally, you should be able to run it unless your PC is from 30000BC or you're using a literal potato. + - Added a native hitbox visualization mode. + - Improved the line-circle intersection algorithm. New algorithm behaves like a circle-polygon intersection. + - Overloaded ObjMove_SetDestAtFrame, where movement interpolation mode can be specified. + - Fixed a bug where the graze count obtained via GetGraze() may desync with the one obtained via EV_GRAZE's event argument. + - Fixed a bug where ObjText_GetTotalWidth/Height may break the font tag. + - Fixed a bug where font text tag properties do not get reset after using ObjText_SetText. + - Obj_GetValue will now ACTUALLY NOT crash the game if the requested value does not exist. + - Renamed the "Obj_[..]ValueR" function series to "Obj_[..]ValueI". + - Removed the constant 'pi'. Please use 'M_PI' instead. + - Changed error messages of some default functions to be more descriptive to aid debugging. + - Greatly improved script variable allocation. + - Added a concatenate-assign operator. (~=) + - Added bitwise operators. (~, &, |, ^^) + - Int values can now be declared with a suffix 'i' or 'I'. + - Static type declaration is planned. + - Added implicit type casting in default script operations, including comparison and assignment. + - Optimized the process of calling default constants. + - The default constants SCREEN_WIDTH and SCREEN_HEIGHT will now change to reflect the settings in th_dnh.def. + - Some functions will now return int values rather than real values. + - Fixed a bug where itoa, atoi, and IntToString would underflow if the input is larger than 2^31-1. (New limit is 2^63-1) + - Fixed a bug where the 3D viewport would get stretched out based on the size of the STG frame. + - Made the game no longer freeze and crash after Alt-Tab'ing out of true fullscreen mode or after waking the desktop from sleep. + - Pseudo-fullscreen mode now stops Windows from drifting off to Dreamland. + - Fixed a mistake involving matrix multiplication order in the internal shader for particle list objects. + - Removed CollectItemsByType and SetItemIntersectionRadius. + - Added new event, EV_COLLECT_ITEM, which triggers when the item starts to move towards the player. + - Fixed a bug where ObjShot_SetIntersectionScale[XY] does not scale the position offset. + - If ObjFile_Open/ObjFile_OpenNW fails, the reason for failure will now be written to the LogWindow. + - The ObjFileB_Read[...] functions no longer throw an error when attempting to read past EOF. + - ObjFileB_GetLastRead can be used to obtain the amount of bytes read in the last read operation. + - Various optimizations. + - Un-Utilized UPX Executable Packer to not-reduce file size. + +1.10c: + - Fixed a bug in the UserShotData where rect can override animation_data. + - Fixed a bug in the UserShotData where collision did not work at all. + - Added functionality to change the color of the delay cloud per-shot. + - Fixed a parser bug with nested single-lined statements. + - Fixed a rare bug where object IDs may get duplicated when objects are created in rapid succession. + - Fixed a bug where the default charset for some fonts are incorrectly determined. + - Utilized UPX Executable Packer to reduce file size. + +1.10b: + - Fixed bugs with logical and ternary statements. + - Improved data packing of common data files. (Files saved with 1.10a are now incompatible.) + - Bug fixes and optimizations. + +1.10a: + - Fixed some random and function-related crashes. + - RenderToTextureXX alpha fix ported+modified from th_dnh_woo. + - Replaced ObjLaser_SetGrazeInvalidFrame with ObjShot_SetGrazeInvalidFrame. + - Alpha channel blending now exists in all blend modes except BLEND_NONE and BLEND_ADD_RGB. + - Fixed a bug where NotifyEvent and SetScriptArgument could not reach package-level scripts when called from a stage-level script. + - Event arguments will no longer be overwritten when notifying nested events inside @Event. + - Utilized variadic argument counts for the functions in the NotifyEvent series. + - Utilized variadic argument counts for the WriteLog function. + - Added transform functions for ObjPatternShot and relevant sample scripts, for former and current ECL modders. + - Please note that they may not be able to fully emulate ECL's behaviours. + - Added functionality to customize delay clouds. + - Added an option to use true fullscreen mode in the config. + - "Operation-assign" operators (+=, -=, ++, etc.) now work on indexed arrays. + - Given: a = [1, 2, 3] + - a[0]++ = [2, 2, 3] + - a[2] *= 3 = [1, 2, 9] + - a += [5, 6] = [6, 8, 3] + - Given: b = [[1, 2], [3, 4], [5, 6]] + - b[0] += 3 = [[4, 5], [3, 4], [5, 6]] + - b[2]-- = [[1, 2], [3, 4], [4, 5]] + - Array indexing/slicing operations now automatically truncate indices. + - Array slicing operation can now reverse an array. + - Given: a = [10, 12, 14, 16, 18, 20] + - a[0..3] = [10, 12, 14] + - a[3..0] = [14, 12, 10] + - a[1..0] = [10] + - a[6..2] = [20, 18, 16, 14] + - a[2..2] = [] + - Added ternary statements. + - NO_CHANGE can now be used in the ObjMove_AddPatternBX functions. + - ObjMove_SetAngle and ObjMove_SetSpeed can now be used on B-pattern objects. + - Line-line intersection is now properly implemented. + - IsIntersected_Line_Circle can now be used in package-level scripts. + - Added a particle renderer object (ObjParticleList) and new relevant sample scripts. + - Added support for vertex indexing. + - Added support for basic directional lighting. + - Improved vertex shader support, and added sample scripts for demonstration. + - Fixed underflowing and overflowing issues with SetColor/SetAlpha functions. + - Fixed a bug where ObjText_SetFontCharacterSet doesn't work at all. + - Added more options to the [font] text tag. + - Available tag options: + - reset + - Resets the text to its original settings. Present in vanilla ph3 as "clear". + - size + - Adjusts font size. Unchanged from vanilla ph3. + - ox/oy + - Adjusts position offset. + - it + - Toggles italic. (true/false or 1/0) + - wg + - Adjusts font weight. + - br/bg/bb + - Adjusts font bottom color. + - tr/tg/tb + - Adjusts font top color. + - or/og/ob + - Adjusts font border color. + - bc + - Adjusts font bottom color as an (r, g, b) list. + - tc + - Adjusts font top color as an (r, g, b) list. + - oc + - Adjusts font border color as an (r, g, b) list. + - Added more options to the [ruby] text tag. + - Available tag options: + - rb + - Sets text. Unchanged from vanilla ph3. + - rt + - Sets ruby(furigana) text. Unchanged from vanilla ph3. + - sz + - Adjusts the ruby text's font size. + - wg + - Adjusts the ruby text's font weight. + - ox + - Adjusts the ruby text's left margin. + - op + - Adjusts the ruby text's side pitch. + - Improved spacing of ruby text. + - ObjFileT now properly reads from and writes to UTF-8 text files. + - ObjFile_OpenNW now allows both reading and writing, unless the file was stored in a .dat archive, in which case all write functions will fail. + - Pulled the plug on Shift-JIS support in favour of proper Unicode (UTF-8 and UTF-8-BOM) handling. + - Better Metasequoia mesh support, and temporarily(?) suspended Elfreina mesh support. Blender .obj mesh support is planned. + - The player object will now set its own movement speed and angle according to user key input. + - Collecting user-defined items now notify EV_GET_ITEM to the player script. + - Minimum custom window size is reduced to 320*240. + - GetShotDataInfoA1 no longer throws an error upon receiving an invalid graphic ID, and will instead return default values. + - Fixed a bug where the right and bottom source rect set with ObjSprite3D_SetSourceDestRect are 1 greater than expected. + - Improved loading of .wav files. + - Attempted to fix a bug where multiple sound objects simultaneously playing the same sound file (>1MB .wav, .ogg, or .mp3) would display strange behaviours. + - Improved the precision of ObjSound_GetWavePosition, and fixed an issue where ObjSound_GetTotalLength would work incorrectly with .ogg files. + - Added bitwise operators. + - Greatly improved the LogWindow's Script panel. + - Added a text showing the available video memory in the LogWindow's Texture panel. + - Added a text showing the used RAM and CPU in the LogWindow's Info panel. + - Enforced semicolons before closing braces. + - Removed ObjShot_AddShotA1/2. + - Various optimizations. + +1.00a: + - Multidimensional array assignments are now possible. + - Arithmetic operations on array(s) are possible. (Left-right order is important) + - [1, 2, 3] + 5 = [6, 7, 8] + - [5, 5, 1] * 2 = [10, 10, 2] + - [2, 3, 4] - [7, 0, 2] = [-5, 3, 1] + - [10, 10, 10] / [5, 2] = [2, 5, 10] + - [2, 3] % [4, 2, 1, 6] = [2, 1] + - 4 + [2, 3, 6, 2] = 8 + - Added support for multiple-pass shaders. + - Shot and item objects no longer respond to changes in X and Y angles. + - Bullet limit of 8192 for performance reasons. + - Multiple hitbox support for shot objects has been removed. + - Vertex shader support. + - Much smaller replay files. + - Added an option to specify the skip mode speed in th_dnh.def. + - Obj_GetValue will not crash the game if the requested value does not exist. \ No newline at end of file diff --git a/docs/GitHub Repository.url b/docs/GitHub Repository.url new file mode 100644 index 0000000..f55b560 --- /dev/null +++ b/docs/GitHub Repository.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=https://github.com/Natashi/Touhou-Danmakufu-ph3sx-2 diff --git a/docs/Naudiz's Style Guide.txt b/docs/Naudiz's Style Guide.txt new file mode 100644 index 0000000..92cac89 --- /dev/null +++ b/docs/Naudiz's Style Guide.txt @@ -0,0 +1,605 @@ +Preamble: + + The following keywords are used to clarify the importance of each convention: MUST, SHOULD, MAY, SHOULD NOT, MUST NOT. + + In the code examples below, the sequence "// ..." (two slashes, one space, three full stops) denotes a line where, in most cases, more code should be written. + However, such code is unnecessary for the purposes of each example. + + Comments from the writer that do not necessarily dictate style guidelines are preceded by the sequence "// NAZ: ". + +1: Identifiers + + 1.1: Variables and Constants + + Note: + + Variables and constants SHOULD be declared with explicit type keywords (float, int, bool, char, string, etc.), unless the type is unknown, + in which case either "let" or "var" is used. These keywords are interchangeable, but the scripter MUST decide on one to use consistently. + + Variables MUST be written using camelCase*, while constants MUST use SCREAMING_SNAKE_CASE. + Related identifiers SHOULD share the leading parts of their names for alphabetization purposes. + + In cases where variables have short names or are uninitialized, multiple variables MAY be declared on the same line, separated by commas. + They SHOULD be of the same type, so fewer keywords are necessary. + + *If necessary, a prefix or suffix MAY be added to a variable in the snake_case style. + + DO: + + float posX, posY; + const int BOSS_RUMIA = 0; + const int BOSS_CIRNO = 1; + + DON'T: + + let xPos; + let yPos; + const RUMIA_BOSS = 0, CIRNO_BOSS = 1; + + + 1.1.1: Local Variables + + Variables defined within a local scope, such as inside a function or task, MUST use camelCase without any underscores. + + EXAMPLE: + + function DoSomething() + { + float posX, posY; + // ... + } + + + 1.1.2: Global Variables + + Variables defined globally in any script SHOULD be denoted with a leading underscore. + This is similar to the notation used for tasks, but with camelCase instead of PascalCase. + + EXAMPLE: + + int _objEnemy; + int _objPlayer; + + @Initialize + { + // ... + } + + + 1.1.3: Parameters + + Function and task parameters SHOULD be denoted with a trailing underscore. + + Parameters SHOULD be declared with type keywords, or either "let" or "var" if unknown. + + EXAMPLE: + + function DoSomethingElse(int foo_, float bar_) + { + // ... + } + + + 1.1.4: Iterators + + Iterator variables declared in for-loops, ascent-loops, and descent-loops SHOULD be named lowercase letters of the alphabet starting with "i", + progressing to the next letter for each nested loop. This convention MAY be bypassed if more semantic information is necessary. + + Iterator variables declared in for-each-loops SHOULD have single-word names prefixed with "i". + + Fun fact: It is possible to add a second iterator to a for-each-loop, which is listed before the first and iterates through the array's indices (starting from 0) instead of its elements. + This variable SHOULD follow the same rules as those declared in for-loops. + + EXAMPLE: + + for (int i = 0; i < 2; i++) { + ascent (j in 0 .. 3) { + descent (k in 0 .. 4) { + // ... + } + } + } + + for each (iObj in arrObj) { + // ... + } + + for each ((i, iObj) in arrObj) { + // ... + } + + + 1.1.5: Constants + + As mentioned previously, constants MUST use SCREAMING_SNAKE_CASE. All constants SHOULD be defined in a dedicated constant library. + Numeric constants SHOULD be integers instead of float numbers (denoted in decimal literals by appending the character "i" at the end, + but this is not necessary if the constant type is explicitly defined). + + + EXAMPLE: + + const int PLAYER_REIMU = 0; + const int PLAYER_MARISA = 1; + const int PLAYER_SAKUYA = 2; + const int PLAYER_SANAE = 3; + + + + 1.2: Functions, Tasks, and Subroutines + + Note: + + + Function, task, and subroutine names all MUST use PascalCase to differentiate them from other identifiers. + The root of the identifier name SHOULD begin with a verb. + + // NAZ: The "Is...Exists" structure is Engrish through and through, but I use it for consistency with built-in function names. + + EXAMPLE: + + function DoSomething() + { + // ... + } + + function GetSomething(int foo_) + { + // ... + } + + function SetSomething(int foo_, float bar_) + { + // ... + } + + function IsSomethingExists(int foo_) + { + // ... + } + + + 1.2.1: Functions + + Functions SHOULD be declared with explicit type keywords in angle brackets, unless the type is unknown or variant. + + Function names MUST use PascalCase with no underscores.* + Function calls require trailing parentheses, even when there are no arguments. + + *Excluding cases where there is a necessary prefix or suffix denoting important information, such as object type. + + EXAMPLE: + + function DoSomething() + { + // ... + } + + function DoSomethingElse(bool foo_, float bar_) + { + DoSomething(); + // ... + } + + function Obj_DoSomething(int obj_) + { + // ... + } + + function DoSomething_Obj_Obj(int obj1_, int obj2_) + { + // ... + } + + + 1.2.2: Tasks + + Task names SHOULD use one of the following styles (and consistently): PascalCase with a leading underscore, OR PascalCase with a leading uppercase T. + The same rules about affixes and parentheses that apply to functions apply here. + + // NAZ: I like to treat my tasks as private routines, so often times you'll see me create a "public" function that calls task nested inside. + + EXAMPLE: + + task _RenderPlayer(int id_) + { + // ... + } + + task _RenderPlayer_Reimu() + { + _RenderPlayer(PLAYER_REIMU); + // ... + } + + + 1.2.3: Subroutines + + Subroutines MUST use PascalCase, and SHOULD include a trailing underscore. Parentheses MAY be used. + + It is possible to use the at sign (@) in place of the "sub" keyword, but scripters SHOULD NOT do so, to prevent confusion with built-in routines (@Initialize, @MainLoop, @Finalize, etc.). + + // NAZ: I don't think I've ever used one of these, lol. I came up with the underscore rule on the fly. + + EXAMPLE: + + sub DoSomethingDifferent_ + { + // ... + } + + + + +2: Whitespace + + Note: + + For the sake of consistency, spaces SHOULD be used instead of tabs in ALL cases. + The default tab is equivalent to 4 spaces; any decent editor should have an option to insert spaces upon pressing the tab key. + + 2.1: Operators + + Expressions and statements consisting of one or more literals and/or identifiers MUST employ one space on both sides of all binary and ternary operators + (= +, -, *, /, ~/, %, ^, ~, +=, -=, *=, /=, ~/=, %=, ^=, ~=, ==, !=, >, <, >=, <=, &&, ||, &, |, ^^, .., ?, :). + + Expressions and statements consisting of an identifier and a unary operator (!, ++, --) MUST NOT employ a space between the operator and operand. + + DO: + + float someNum = 6 * 9 + 4 / 20 - 6 % 66; + someNum++; + + DON'T: + + float someNum = 6*9+4/20-6%66; + someNum ++; + + // NAZ: I will send you to the Shadow Realm if you don't put spaces in between your operators like in the "DON'T" example. It's entirely unreadable for me. + + 2.2: Variables and Constants + + Variable and constant declaration and assignment statements MUST employ one space between the keyword (let, var, const) and the identifier, + and on both sides of the assignment operator (=) if applicable.* + + As stated previously, if identifiers have short names or are uninitialized, their declarations MAY go on the same line, separated by commas and followed by spaces. + + *Additional spaces MAY be used to vertically align the operator and right-hand side of each statement in a group of statements. See the example. + + EXAMPLE: + + const int BGM_TITLE = 0; + const int BGM_1_ROAD = 1; + const int BGM_1_BOSS = 2; + const int BGM_GAMEOVER = 3; + + + 2.3: Functions, Tasks, and Subroutines + + Function, task, and subroutine definitions MUST employ one space between the keyword (function, task, or sub) and the identifier, + and NO space between the identifier and the parentheses, differently from flow control statements. + Parameters contained inside the parentheses MUST employ one space between each identifier, i.e. after each comma. + + The opening and closing braces of a function, task, or subroutine block MUST go on their own lines, and all lines in between them MUST be indented. + There MUST also be an empty line following each closing brace. + The same rules also apply to @Initialize, @MainLoop, @Event, @Finalize, and @Loading. + + // Natashi: I don't like placing opening curly braces on newlines. *turns half of your body into pizza dough* + + Function, task, and subroutine invocations MUST NOT include a space between the identifier and parentheses, if applicable. + Like parameters, arguments MUST be separated by whitespace, i.e. after each comma. + + Function and task arguments MAY span several indented lines for readability purposes. + There SHOULD be an empty space following each multi-line function call, unless it precedes a closing brace or parenthesis. + + // NAZ: This is only really applicable if the arguments get unbearably long, though. The example just demonstrates it just because. + + EXAMPLE: + + @Initialize + { + DoSomething( + true, + 1, + 1.1, + 'e', + "abc" + ); + + // ... + } + + function DoSomething(bool foo_, int bar_, float baz_, char qux_, string quux_) + { + // ... + } + + + 2.4: Flow Control Statements + + Flow control statements MUST employ whitespace on both sides of each keyword + (if, else, loop, while, ascent, descent, in, for, each, alternative, case, others, switch, default, local, yield, break, continue), + unless said keyword by itself is a statement (yield, break, continue), in which case it is simply terminated with a semicolon. + + For conditionals and loops, the opening curly brace SHOULD go on the same line as the preceding keyword or closing parenthesis, following a space.* + The closing curly brace SHOULD go on its own line, except in the case of "else" and "else if" which SHOULD be written after a space following the closing brace. + Loops and conditional structures SHOULD be followed by an empty line. + + For for-loops, each statement ending in a semicolon MUST be followed by a space, i.e. the first and second. + The second and third statements may be omitted, in which case a space SHOULD be used instead. + When statements are combined with commas, there MUST be a space after each of them. + + *Conditionals and loops containing a single statement terminated with a semicolon MAY be written without curly braces, + in which case they SHOULD be written on the same line as the rest of the statement, following a space. + Nested conditionals and loops may also be written without curly braces, provided that there is only one semicolon-terminated statement within it. + Alternative cases written this way MAY use additional spaces to align their contents. + + EXAMPLE 1 (VERBOSE): + + for (int i = 1, j = 2; i <= 10; i++, j--) { + alternative (i) + case (1) { + WriteLog("i is 1!", "j is 2!"); + } + case (2) { + WriteLog("i is 2!", "j is 1!"); + } + others { + WriteLog("I can't count that high!"); + } + + if (i >= 3) { + break; + } else { + loop (5) { + yield; + } + } + } + + EXAMPLE 2 (CONCISE): + + for (int i = 1, j = 2; i <= 10; i++, j--) { + alternative (i) + case (1) WriteLog("i is 1!", "j is 2!"); + case (2) WriteLog("i is 2!", "j is 1!"); + others WriteLog("I can't count that high!"); + + if (i >= 3) break; + else loop (5) yield; + } + + // NAZ: With "wait" being built-in there's no use case for "loop (n) yield;". + // NAZ: I simply wanted to demonstrate nested structures and how they can be shortened. + + 2.5: Arrays + + Arrays elements MUST be separated by whitespace, i.e. after each comma. + + Multidimensional or otherwise verbose arrays MAY be written across several indented lines. + The initial opening square brace MUST go on the same line as the operator that precedes it. + The new lines and indenting SHOULD be consistent throughout each dimension of the array. + There SHOULD be an empty space following each multi-line array, unless it precedes a closing brace or parenthesis. + + For performance reasons, arrays SHOULD be indexed as infrequently as possible. + If only one element is needed, storing it in a variable is recommended. + + EXAMPLE: + + int[] arrSmall = [1, 2, 3]; + int[][] arrBig = [ + [1, 2, 3], + [4, 5, 6, 7], + [8, 9, 10, 11, 12] + ]; + + int[][][] arrBigger = [ + [ + [1, 2, 3], + [4, 5, 6, 7], + ], [ + [8, 9, 10, 11, 12], + [13, 14, 15, 16, 17, 18], + [19, 20, 21, 22, 23, 24, 25], + ] + ]; + + int numSmall = arrSmall[2]; + int numBig = arrBig[2][4]; + int numBigger = arrBigger[1][2][6]; + + + +3: Organization + + 3.1: Script Structure + + All scripts SHOULD have their sections organized in the following order: + + 1. Headers (#TouhouDanmakufu, #ScriptVersion*, #Title, #Text, #System, #Background, #BGM) + 2. #include directives + 3. Global variables + 4. Predefined routines (@Initialize, @Event, @MainLoop, @Finalize, @Loading) + 5. Script-specific routines + + *The #ScriptVersion header can only take one possible argument (3), and SHOULD be omitted altogether. + + EXAMPLE: + + #TouhouDanmakufu[Stage] + #Title["Example Stage"] + #Text["An example of a stage script."] + #System["script/script_system.dnh"] + + #include "script/include_stg.dnh" + + int _idScript; + + @Initialize + { + _idScript = GetOwnScriptID(); + _Main(); + } + + @MainLoop + { + yield; + } + + @Finalize + { + WriteLog("Game over!"); + } + + task _Main() + { + while (GetPlayerState() != STATE_END) yield; + CloseScript(_idScript); + } + + + 3.2: Included Files + + As a preface, what the #include directive does is tell the engine to copy the contents of a given text file and paste them into the script, replacing the #include directive. + If a file has already been included in the script, it will be skipped. + + To reduce the amount of boilerplate in each script file, the scripter SHOULD create files with the express purpose of including several other files, ideally in a hierarchical manner. + + DO: + // In include_main.dnh + + #include "./lib_main.dnh" + #include "./lib_const.dnh" + #include "./lib_math.dnh" + #include "./lib_render.dnh" + #include "./lib_event.dnh" + + // In include_stg.dnh + + #include "./include_main.dnh" + #include "./lib_stg.dnh" + #include "./lib_move.dnh" + #include "./lib_shot.dnh" + #include "./lib_enemy.dnh" + + // In include_boss.dnh + + #include "./include_stg.dnh" + #include "./lib_boss.dnh" + #include "./lib_anim.dnh" + #include "./lib_spell.dnh" + + // In the main script + + #TouhouDanmakufu[Single] + // ... + + #include "script/include_boss.dnh" + + @Initialize + { + // ... + } + + + DON'T: + + // In the main script + + #TouhouDanmakufu[Single] + // ... + + #include "./lib_main.dnh" + #include "./lib_const.dnh" + #include "./lib_math.dnh" + #include "./lib_render.dnh" + #include "./lib_event.dnh" + #include "./lib_stg.dnh" + #include "./lib_move.dnh" + #include "./lib_shot.dnh" + #include "./lib_enemy.dnh" + #include "./lib_boss.dnh" + #include "./lib_anim.dnh" + #include "./lib_spell.dnh" + + @Initialize + { + // ... + } + + + // NAZ: These file paths assume that the script as well as all of the library files are located in the base script directory. + // NAZ: Ideally, you should have a dedicated lib folder, possibly with subfolders corresponding to the libraries contained in each "include" file. + + 3.3: Script Routines + + Scripts (particularly those in which danmaku is created) SHOULD call a task named _Main (or TMain, depending on your chosen style) from @Initialize. + This task SHOULD be the ultimate source of all other script-specific routine invocations. + + The scripter SHOULD make use of nesting for a few reasons: + + 1. To ensure that variables are limited to their intended scopes. + 2. To prevent the need to pass variables around unnecessarily via arguments. + + EXAMPLE 1 (NON-NESTED): + + task _Main() + { + float dir; + + loop { + dir = rand(0, 360); + _Fire(dir); + wait(60); + + } + } + + task _Fire(float dir_) + { + float speed = 1; + + loop (5) { + Shoot(speed, dir_); + speed++; + wait(2); + } + } + + function Shoot(float speed_, float dir_) + { + int obj = CreateShotA1(someX, someY, speed_, dir_, someID, 15); + ObjShot_SetDeleteFrame(obj, 180); + } + + EXAMPLE 2 (NESTED): + + task _Main() + { + float dir; + + loop { + dir = rand(0, 360); + _Fire(); + wait(60); + } + + task _Fire() + { + float speed = 1; + + loop (5) { + Shoot_; + speed++; + wait(2); + } + + sub Shoot_ + { + int obj = CreateShotA1(someX, someY, speed, dir, someID, 15); + ObjShot_SetDeleteFrame(obj, 180); + } + } + } + + // NAZ: These examples are intentionally bare-bones and only exist for the purposes of demonstrating how nesting can simplify task and function signatures and establish a sense of hierarchy. + diff --git a/docs/New Functions Documentation.txt b/docs/New Functions Documentation.txt new file mode 100644 index 0000000..7f4376a --- /dev/null +++ b/docs/New Functions Documentation.txt @@ -0,0 +1,5053 @@ +ALL ARGUMENTS ARE FLOATS UNLESS STATED OTHERWISE + "T": Any type + +----------------------------------------------> [Base Script] <---------------------------------------------- + + --------------------------------> New Constants <-------------------------------- + + M_PI = pi ; 3.14159265358979323846 + M_PI_2 = M_PI / 2 ; 1.57079632679489661923 + M_PI_4 = M_PI / 4 ; 0.78539816339744830962 + M_PI_X2 = M_PI * 2 ; 6.28318530717958647693 + M_PI_X4 = M_PI * 4 ; 12.5663706143591729539 + M_1_PI = 1 / M_PI ; 0.31830988618379067154 + M_2_PI = 2 / M_PI ; 0.63661977236758134308 + M_SQRTPI = sqrt(M_PI) ; 1.772453850905516027298 + M_1_SQRTPI = 1 / sqrt(M_PI) ; 0.56418958354775628695 + M_2_SQRTPI = 2 / sqrt(M_PI) ; 1.128379167095512573896 + M_SQRT2 = sqrt(2) ; 1.4142135623730950488 + M_SQRT2_2 = sqrt(2) / 2 ; 0.7071067811865475244 + M_SQRT2_X2 = sqrt(2) * 2 ; 2.8284271247461900976 + M_E = e ; 2.71828182845904523536 + M_LOG2E = log2(e) ; 1.44269504088896340736 + M_LOG10E = log10(e) ; 0.43429448190325182765 + M_LN2 = ln(2) ; 0.69314718055994530942 + M_LN10 = ln(10) ; 2.30258509299404568402 + M_PHI = (1 + sqrt(5)) / 2 ; 1.61803398874989484821 + M_1_PHI = 1 / M_PHI ; 0.6180339887498948482 + + INF = infinity float + NAN = NaN float + + --------------------------------> Basic Operations <-------------------------------- + + __DEBUG_BREAK + Description: + Triggers a debug break. For developers. + + wait + Arguments: + 1) (int) frame + Description: + Pauses the execution for the given amount of frames. + + Much faster than loop(n){yield;} + + typeof + Arguments: + 1) (T) value + Returns: + (int) type + Description: + Returns the type of the given value. + + Example: + -60i -> VAR_INT + 920 -> VAR_FLOAT + false -> VAR_BOOL + "str" -> VAR_STRING + [8, 0, 2] -> VAR_ARRAY + + ftypeof + Arguments: + 1) (T) value + Returns: + (int) type + Description: + Returns the root type of the given value. + + Example: + 920 -> VAR_FLOAT + false -> VAR_BOOL + "str" -> VAR_CHAR + [8, 0, 2] -> VAR_FLOAT + [[["a"]]] -> VAR_CHAR + + resize + Arguments: + 1) (T[]) array + 2) (int) new size + Returns: + (T[]) result + Description: + Resizes the given array. + The array must not be a null array. + + resize (Overload) + Arguments: + 1) (T[]) array + 2) (int) new size + 3) (T) fill value + Returns: + (T[]) result + Description: + Overloaded with 3 arguments. + + Resizes the given array. + + If the new size is larger than the old size, newly inserted elements will be assigned the fill value. + Unless the array is a null array, the fill value's type must be convertible to the array's element type. + + insert + Arguments: + 1) (T[]) array + 2) (int) insert position + 3) (T) value + Returns: + (T[]) result + Description: + Inserts the given value into the given position of the array. + Insertion method is "insert-before". + + contains + Arguments: + 1) (T[]) array + 2) (T) value + Returns: + (bool) result + Description: + Checks if the given value is present as an element of the given array. + + replace + Arguments: + 1) (T[]) array + 2) (T) replace from + 2) (T) replace to + Returns: + (T[]) result + Description: + Replaces all occurences of the given element with the other in the array. + + remove + Arguments: + 1) (T[]) array + 2) (T) value + Returns: + (T[]) result + Description: + Removes all occurences of the given element in the array. + + --------------------------------> Type Casting <-------------------------------- + + as_int + Arguments: + 1) (T) value + Returns: + (int) result + Description: + Returns the given value casted to an int value. + + as_float + Arguments: + 1) (T) value + Returns: + (float) result + Description: + Returns the given value casted to a float value. + + as_bool + Arguments: + 1) (T) value + Returns: + (bool) result + Description: + Returns the given value casted to a bool value. + + as_char + Arguments: + 1) (T) value + Returns: + (char) result + Description: + Returns the given value casted to a char value. + + as_int_array + Arguments: + 1) (T[]) array + Returns: + (int[]) result + Description: + Casts array elements to ints, then returns the result. + + Casting is recursive. + + Example: + as_int_array([[true, true], [false, true]]); //-> [[1, 1], [0, 1]] + + as_float_array + Arguments: + 1) (T[]) array + Returns: + (float[]) result + Description: + Casts array elements to floats, then returns the result. + + Casting is recursive. + + as_bool_array + Arguments: + 1) (T[]) array + Returns: + (bool[]) result + Description: + Casts array elements to bools, then returns the result. + + Casting is recursive. + + as_char_array + Arguments: + 1) (T[]) array + Returns: + (char[]) result + Description: + Casts array elements to chars, then returns the result. + + Casting is recursive. + Not an alias of ToString. + + as_x_array + Arguments: + 1) (T[]) array + 2) (const) type + Returns: + (T[]) result + Description: + Casts array elements to the given type, then returns the result. + + Supported types: + VAR_INT + VAR_FLOAT + VAR_BOOL + VAR_CHAR + + Casting is recursive. + + --------------------------------> Bitwise Operations <-------------------------------- + + bit_not + Arguments: + 1) (int) value + Returns: + (int) result + Description: + Performs a bitwise NOT operation. + + bit_and + Arguments: + 1) (int) value 1 + 2) (int) value 2 + Returns: + (int) result + Description: + Performs a bitwise AND operation. + + bit_or + Arguments: + 1) (int) value 1 + 2) (int) value 2 + Returns: + (int) result + Description: + Performs a bitwise OR operation. + + bit_xor + Arguments: + 1) (int) value 1 + 2) (int) value 2 + Returns: + (int) result + Description: + Performs a bitwise XOR operation. + + bit_left + Arguments: + 1) (int) value + 2) (int) shift factor + Returns: + (int) result + Description: + Performs a bitwise left shift operation. + + bit_right + Arguments: + 1) (int) value + 2) (int) shift factor + Returns: + (int) result + Description: + Performs a bitwise right shift operation. + + --------------------------------> Float Utilities <-------------------------------- + + Float_Classify + Arguments: + 1) x + Returns: + (const) result + Description: + Classifies the given float value. + + Possible return values: + - FLOAT_TYPE_ZERO ; Value is either +0 or -0. + - FLOAT_TYPE_NORMAL ; Value is a normal float. + - FLOAT_TYPE_SUBNORMAL ; Value is a subnormal float. (https://en.wikipedia.org/wiki/Subnormal_number) + - FLOAT_TYPE_INFINITY ; Value is either +infinity or -infinity. + - FLOAT_TYPE_NAN ; Value is not-a-number. + + Float_IsNan + Arguments: + 1) x + Returns: + (bool) result + Description: + Returns true if the given float is NaN. + + Float_IsInf + Arguments: + 1) x + Returns: + (bool) result + Description: + Returns true if the given float is +infinity or -infinity. + + Float_GetSign + Arguments: + 1) x + Returns: + (float) sign + Description: + Returns +1.0 if the given float is positive, and -1.0 if the given float is negative. + + Float_CopySign + Arguments: + 1) x + 2) y + Returns: + (float) result + Description: + Copies the sign of x to y, and returns the result. + + --------------------------------> Maths <-------------------------------- + + clamp + Arguments: + 1) x + 2) lower bound + 3) upper bound + Returns: + (float) result + Description: + Returns x clamped between the specified range. + + log2 + Arguments: + 1) x + Returns: + (float) result + Description: + Returns base-2 logarithm of x. + + logn + Arguments: + 1) x + 2) base + Returns: + (float) result + Description: + Returns base-n logarithm of x. + + erf + Arguments: + 1) x + Returns: + (float) result + Description: + Returns the error function value of x. + + erf(x) = (2/sqrt(pi)) * integral(0, x, "e^(-t^2) dt") + + gamma + Arguments: + 1) x + Returns: + (float) result + Description: + Returns the gamma function value of x. + + gamma(z + 1) = integral(0, infinity, "(x^z)(e^(-x)) dx") + + exp + Arguments: + 1) value + Returns: + (float) result + Description: + Returns e (Euler's number) raised to the power of x. + + sqrt + Arguments: + 1) x + Returns: + (float) result + Description: + Returns the square root of x. + Much faster than pow(x, 0.5). + + cbrt + Arguments: + 1) x + Returns: + (float) result + Description: + Returns the cube root of x. + Equivalent to (x ^ (1/3)). + + nroot + Arguments: + 1) x + 2) root + Returns: + (float) result + Description: + Returns the nth root of x. + Equivalent to pow(x, 1 / root). + + hypot + Arguments: + 1) a + 2) b + Returns: + (float) result + Description: + Returns the hypotenuse of the triangle formed by the two given values. + + hypot(a, b) = sqrt(a * a + b * b) + + distance + Arguments: + 1) x1 + 2) y1 + 3) x2 + 4) y2 + Returns: + (float) result + Description: + Returns distance between the given two points. + + distance(x1, y1, x2, y2) = hypot(x1 - x2, y1 - y2) + + distancesq + Arguments: + 1) x1 + 2) y1 + 3) x2 + 4) y2 + Returns: + (float) result + Description: + Returns square of the distance between the given two points. + + distancesq(x1, y1, x2, y2) = (x1 - x2)^2 + (y1 - y2)^2 + + dottheta + Arguments: + 1) x1 + 2) y1 + 3) x2 + 4) y2 + Returns: + (float) result (degrees) + Description: + Returns angle (in degrees) between the given two points. + + dottheta(x1, y1, x2, y2) = atan2(y2 - y1, x2 - x1) + + rdottheta + Arguments: + 1) x1 + 2) y1 + 3) x2 + 4) y2 + Returns: + (float) result (radians) + Description: + Returns angle (in radians) between the given two points. + + rdottheta(x1, y1, x2, y2) = ratan2(y2 - y1, x2 - x1) + + --------------------------------> Trigonometry and Angular Maths <-------------------------------- + + sincos + Arguments: + 1) angle + Returns: + (float[2]) [sin(angle), cos(angle)] + + rsin + Arguments: + 1) angle + Returns: + (float) result + Description: + sin() for radians input. + + rcos + Arguments: + 1) angle (radians) + Returns: + (float) result + Description: + cos() for radians input. + + rtan + Arguments: + 1) angle (radians) + Returns: + (float) result + Description: + tan() for radians input. + + rsincos + Arguments: + 1) angle (radians) + Returns: + (float[2]) result + Description: + sincos() for radians input. + + rasin + Arguments: + 1) value + Returns: + (float) result + Description: + asin() for radians output. + + racos + Arguments: + 1) value + Returns: + (float) result + Description: + acos() for radians output. + + ratan + Arguments: + 1) y + 2) x + Returns: + (float) result + Description: + atan() for radians output. + + ratan2 + Arguments: + 1) value + Returns: + (float) result + Description: + atan2() for radians output. + + ToDegrees + Arguments: + 1) angle + Returns: + (float) result + Description: + Converts the given angle to degrees. + + ToRadians + Arguments: + 1) angle + Returns: + (float) result + Description: + Converts the given angle to radians. + + NormalizeAngle + Arguments: + 1) angle (degrees) + Returns: + (float) result + Description: + Normalizes the given angle. (Range = [0, 360)) + + NormalizeAngleR + Arguments: + 1) angle (radians) + Returns: + (float) result + Description: + Normalizes the given angle. (Range = [0, 2pi)) + + AngularDistance + Arguments: + 1) angle from (degrees) + 2) angle to (degrees) + Returns: + (float) result + Description: + Calculates the shortest angular distance between the given angles. (Range = [-180, 180)) + + AngularDistanceR + Arguments: + 1) angle from (radians) + 2) angle to (radians) + Returns: + (float) result + Description: + Calculates the shortest angular distance between the given angles. (Range = [-pi, pi)) + + ReflectAngle + Arguments: + 1) ray angle (degrees) + 2) surface angle (degrees) + Returns: + (float) result + Description: + Calculates the given ray's angle of reflection upon a surface of the given angle. (Range = [0, 360)) + + ReflectAngleR + Arguments: + 1) ray angle (radians) + 2) surface angle (radians) + Returns: + (float) result + Description: + Calculates the given ray's angle of reflection upon a surface of the given angle. (Range = [0, 2pi)) + + --------------------------------> Interpolation <-------------------------------- + + For the functions in this section, refer to these Desmos graph plot. + "Basic" interpolations -> https://www.desmos.com/calculator/m8dnz348cq + Bezier interpolations -> https://www.desmos.com/calculator/q1uptzx8ti + + Interpolate_Linear + Arguments: + 1) a + 2) b + 3) x + Returns: + IF a, b are not arrays + (float) result + ELSE + (float[]) result array + Description: + Returns the result of interpolation between a and b, using x as the interpolation value. + Interpolation method is linear. + Direct formula is (a + (b - a) * (x)) + Represented by the red graph. + + When interpolating between two arrays, they must be of the same size. + + Interpolate_Smooth + Arguments: + 1) a + 2) b + 3) x + Returns: + IF a, b are not arrays + (float) result + ELSE + (float[]) result array + Description: + Returns the result of interpolation between a and b, using x as the interpolation value. + Interpolation method is first-order smoothstep curve. + Direct formula is (a + (b - a) * (x^2 * (3 - 2 * x))) + Represented by the blue graph. + + When interpolating between two arrays, they must be of the same size. + + Interpolate_Smoother + Arguments: + 1) a + 2) b + 3) x + Returns: + IF a, b are not arrays + (float) result + ELSE + (float[]) result array + Description: + Returns the result of interpolation between a and b, using x as the interpolation value. + Interpolation method is second-order smoothstep curve. + Direct formula is (a + (b - a) * (x^3 * (x * (x * 6 - 15) + 10))) + Represented by the green graph. + + When interpolating between two arrays, they must be of the same size. + + Interpolate_Accelerate + Arguments: + 1) a + 2) b + 3) x + Returns: + IF a, b are not arrays + (float) result + ELSE + (float[]) result array + Description: + Returns the result of interpolation between a and b, using x as the interpolation value. + Interpolation method is parabolic. + Direct formula is (a + (b - a) * (x^2)) + Represented by the purple graph. + + When interpolating between two arrays, they must be of the same size. + + Interpolate_Decelerate + Arguments: + 1) a + 2) b + 3) x + Returns: + IF a, b are not arrays + (float) result + ELSE + (float[]) result array + Description: + Returns the result of interpolation between a and b, using x as the interpolation value. + Interpolation method is inverse parabolic. + Direct formula is (a + (b - a) * (1 - (1 - x)^2)) + Represented by the black graph. + + When interpolating between two arrays, they must be of the same size. + + Interpolate_Modulate + Arguments: + 1) a + 2) b + 3) c + 4) x + Returns: + (float) result + Description: + Returns the result of interpolation between a and b, using x as the interpolation value. + Interpolation method is sine. + Direct formula is (a + (b - a) * (x + (rsin(2pi * x) / (2pi)) * c)) + Represented by the dotted red graph. + + Interpolate_Overshoot + Arguments: + 1) a + 2) b + 3) c + 4) x + Returns: + (float) result + Description: + Returns the result of interpolation between a and b, using x as the interpolation value. + Interpolation method is half sine. + Direct formula is (a + (b - a) * (x + (rsin(pi * x) / pi) * c)) + Represented by the dotted blue graph. + + Interpolate_QuadraticBezier + Arguments: + 1) a + 2) b + 3) c + 4) x + Returns: + (float) result + Description: + Calculates a coordinate component of a quadratic Bezier curve. + Direct formula is ((a * (1 - x)^2) + (2 * c * x * (1 - x)) + (b * x^2)) + Represented by the red graph. + + Interpolate_CubicBezier + Arguments: + 1) a + 2) b + 3) c1 + 4) c2 + 5) x + Returns: + (float) result + Description: + Calculates a coordinate component of a cubic Bezier curve. + Direct formula is ((a * (1 - x)^3) + (3 * c1 * x * (1 - x)^2) + (3 * c2 * x^2 * (1 - x)) + (b * x^3)) + Represented by the red graph. + + Interpolate_Hermite + Arguments: + 1) start x + 2) start y + 3) end x + 4) end y + 5) starting point tangent vector magnitude + 6) starting point tangent vector angle (degrees) + 5) ending point tangent vector magnitude + 6) ending point tangent vector angle (degrees) + 9) x + Returns: + (float[2]) [x, y] + Description: + Calculates the position along the given cubic Hermite spline curve. + + https://en.wikipedia.org/wiki/Cubic_Hermite_spline + + Interpolate_X + Arguments: + 1) a + 2) b + 3) x + 4) (int) interpolation type + Returns: + IF a, b are not arrays + (float) result + ELSE + (float[]) result array + Description: + Interpolates between a and b using x with the given interpolation type. + + Available interpolation types: + LERP_LINEAR: + Interpolate_Linear + LERP_SMOOTH: + Interpolate_Smooth + LERP_SMOOTHER: + Interpolate_Smoother + LERP_ACCELERATE: + Interpolate_Accelerate + LERP_DECELERATE: + Interpolate_Decelerate + + Interpolate_X_PackedInt + Arguments: + 1) (int) a + 2) (int) b + 3) x + 4) (int) interpolation type + Returns: + (int[]) result array + Description: + Divides a and b (both 8-byte ints) into eight 1-byte chunks, performs interpolation on each pair, and recombines them to return the result. + + Example: + Interpolate_X_PackedInt(0x37ff4040, 0xaa001010, 0.5, LERP_LINEAR); //result = 0x707f2828 + + Interpolate_X_Angle + Arguments: + 1) a (degrees) + 2) b (degrees) + 3) x + 4) (int) interpolation type + Returns: + (float) angle (degrees) + Description: + Interpolates between angles a and b using x with the given interpolation type. + + Equivalent to: + NormalizeAngle(a + Interpolate_X(0, AngularDistance(a, b), x, type)); + + Interpolate_X_AngleR + Arguments: + 1) a (radians) + 2) b (radians) + 3) x + 4) (int) interpolation type + Returns: + (float) angle (radians) + Description: + Interpolates between angles a and b using x with the given interpolation type. + + Equivalent to: + NormalizeAngleR(a + Interpolate_X(0, AngularDistanceR(a, b), x, type)); + + Interpolate_X_Array + Arguments: + 1) (T[]) values + 2) x + 3) (int) interpolation type + Returns: + (float) result + Description: + Interpolates between multiple elements of the array. + + Examples: + Interpolate_X_Array([a, b, c, d], 0.2, LERP_LINEAR); + = Interpolate_X(a, b, 0.2, LERP_LINEAR); + + Interpolate_X_Array([a, b, c, d], 1.5, LERP_LINEAR); + = Interpolate_X(b, c, 0.5, LERP_LINEAR); + + Interpolate_X_Array([a, b, c, d], 2.9, LERP_LINEAR); + = Interpolate_X(c, d, 0.9, LERP_LINEAR); + + --------------------------------> Random <-------------------------------- + + rand_int + Arguments: + 1) (int) min + 2) (int) max + Returns: + (int) random integer + Description: + Returns a random integer within the range [a, b]. + + rand_int(a, b) = as_int(rand(a, b + 0.99999)) + + prand + Arguments: + 1) min + 2) max + Returns: + (float) random value + Description: + Exactly like rand(), but the seed of which doesn't get saved to replays, and does not affect the state of rand(). + + prand_int + Arguments: + 1) (int) min + 2) (int) max + Returns: + (int) random integer + Description: + Returns a random integer within the range [a, b] using the prand() function. + + prand_int(a, b) = as_int(prand(as_int(a), as_int(b) + 0.99999)) + + psrand + Arguments: + 1) (int) seed + Description: + Sets the seed for prand and prand_int. + + count_rand + Returns: + (int) count + Description: + Returns the amount of number rand or rand_int have been used. + + Resets when restarting the game or exiting to the script select menu. + + count_prand + Returns: + (int) count + Description: + Returns the amount of number prand or prand_int have been used. + + Resets when restarting the game or exiting to the script select menu. + + reset_count_rand + Description: + Sets the rand count to 0. + + reset_count_prand + Description: + Sets the prand count to 0. + + --------------------------------> Rotation Maths <-------------------------------- + + Rotate2D + Arguments: + 1) x + 2) y + 3) angle + Returns: + (float[2]) rotated position [x, y] + Description: + Rotates the given (x, y) point around the origin (0, 0). + + Direct formula is: + x = x * cos(angle) - y * sin(angle) + y = x * sin(angle) + y * cos(angle) + + Rotate2D (overload) + Arguments: + 1) x + 2) y + 3) angle + 4) origin x + 5) origin y + Returns: + (float[2]) rotated position [x, y] + Description: + Overloaded with 5 arguments. + + Rotates the given (x, y) point around the given origin. + + Direct formula is: + _x = x - ox + _y = y - oy + x = ox + (_x * cos(angle) - _y * sin(angle)) + y = oy + (_x * sin(angle) + _y * cos(angle)) + + Rotate3D + Arguments: + 1) x + 2) y + 3) z + 4) X angle + 5) Y angle + 6) Z angle + Returns: + (float[3]) rotated position [x, y, z] + Description: + Rotates the given (x, y, z) point around the origin (0, 0) with the given Euler angles. + + Direct formula is: + x = x * (cos(angY) * cos(angZ) - sin(angX) * sin(angY) * sin(angZ)) + y * (-cos(angX) * sin(angZ)) + z * (sin(angY) * cos(angZ) + sin(angX) * cos(angY) * sin(angZ)) + y = x * (cos(angY) * sin(angZ) + sin(angX) * sin(angY) * cos(angZ)) + y * (cos(angX) * cos(angZ)) + z * (sin(angY) * sin(angZ) - sin(angX) * cos(angY) * cos(angZ)) + z = x * (-cos(angX) * sin(angY)) + y * (sin(angX)) + z * (cos(angX) * cos(angY)) + + Rotate3D (overload) + Arguments: + 1) x + 2) y + 3) z + 4) X angle + 5) Y angle + 6) Z angle + 7) origin x + 8) origin y + 9) origin z + Returns: + (float[3]) rotated position [x, y, z] + Description: + Rotates the given (x, y, z) point around the given origin with the given Euler angles. + + Direct formula is: + _x = x - ox + _y = y - oy + _z = z - oz + x = ox + (_x * (cos(angY) * cos(angZ) - sin(angX) * sin(angY) * sin(angZ)) + _y * (-cos(angX) * sin(angZ)) + _z * (sin(angY) * cos(angZ) + sin(angX) * cos(angY) * sin(angZ))) + y = oy + (_x * (cos(angY) * sin(angZ) + sin(angX) * sin(angY) * cos(angZ)) + _y * (cos(angX) * cos(angZ)) + _z * (sin(angY) * sin(angZ) - sin(angX) * cos(angY) * cos(angZ))) + z = oz + (_x * (-cos(angX) * sin(angY)) + _y * (sin(angX)) + _z * (cos(angX) * cos(angY))) + + --------------------------------> String <-------------------------------- + + atoi (overload) + Arguments: + 1) (string) value + 2) (int) base + Returns: + (int) value + Description: + Overloaded with 2 arguments. + + Converts the string into an integer with the specified base. + + Examples: + atoi("3511", 10); //3511 + atoi("3511", 16); //13585 + atoi("0x7f3", 16); //2035 + + SplitString2 + Arguments: + 1) (string) source string + 2) (string) pattern + Returns: + (string[]) split result + Description: + Splits the string at the given pattern. + + Examples: + SplitString2("ab3cd3ef3g", "3"); + //Result: ["ab", "cd", "ef", "g"] + + SplitString2("1b23abc45a6abc789c", "abc"); + //Result: ["1b23", "45a6", "789c"] + + SplitString("1b23abc45a6abc789c", "abc"); + //Result: ["1", "23", "", "", "45", "6", "", "", "789", ""] + + StringFormat + Arguments: + 1) (string) source string + 2) (string) argument types + 3+) (T) format arguments... + Returns: + (string) formatted string + Description: + Formats the string in the style of sprintf. + + The number of format arguments must match the number of argument types. + + Make sure that the amount of format arguments match the formatting tokens in the source string, + the game may crash if the formatting token count exceeds the format argument count. + + Available argument types: + - d: Argument is passed a 32-bit integer (int). + - l: Argument is passed a 64-bit integer (long int). + - f: Argument is passed a floating point number (double). + - s: Argument is passed a string (wstring). + + Example: + StringFormat("This is a %s", "s", "string."); + //Result: This is a string. + + StringFormat("The value is %s", "s", 32); + //Result: The value is 32.000000 + + StringFormat("%f + %d = %.2f", "fdf", 1.15836, 2.12, 3.27836); + //Result: 1.158360 + 2 = 3.28 + + StringFormat("0x%08x is %d", "ll", 8023465, 8023465); + //Result: 0x007a6da9 is 8023465 + + StringFormat("0x%016llx %s %lld", "lsl", 2275101568023465, "is", 2275101568023465); + //Result: 0x000815315cca3ba9 is 2275101568023465 + + RegexMatch + Arguments: + 1) (string) source string + 2) (string) pattern + Returns: + (string[]) match groups + Description: + Uses regular expression to match patterns in a given string. + Returns a string array of matches. + + Example: + RegexMatch("Voyage 1969", "[0-9]+"); + //Result: ["1969"] + + RegexMatch("S231 A001 S101 S000", "S([0-9]{3})"); + //Result: "S231", "231"] + + RegexMatchRepeated + Arguments: + 1) (string) source string + 2) (string) pattern + Returns: + (string[][]) array of match groups + Description: + Behaves like RegexMatch, but returns all matches in the string rather than only the first match. + + Example: + RegexMatchRepeated("Voyage 1969", "[0-9]+"); + //Result: [["1969"]] + + RegexMatchRepeated("S231 A001 S101 S0040", "S([0-9]{3})"); + //Result: [["S231", "231"], ["S101", "101"], ["S004", "004"]] + + RegexReplace + Arguments: + 1) (string) source string + 2) (string) pattern + 2) (string) replacing string + Returns: + (string) replace result + Description: + Uses regular expression to replace patterns in a given string. + Returns the pattern-replaced string. + + Example: + RegexReplace("Voyage 1969", "[0-9]+", "1970"); + //Result: "Voyage 1970" + + RegexReplace("Example String", "(a|e|i)", "*"); + //Result: "Ex*mpl* Str*ng" + + RegexReplace("Red, Green, and Blue", "[A-Z]+[a-zA-Z]*", "\'$&\'"); + //Result: "'Red', 'Green', and 'Blue'" + + --------------------------------> File Path and Archives <-------------------------------- + + GetArchiveFilePathList + Arguments: + 1) (string) archive path + 2) (bool) print full path + Returns: + (string[]) file names of stored entries + Description: + Returns an array of all filepaths stored inside the specified archive. + The archive must have already been loaded with AddArchiveFile, otherwise an empty array will be returned. + + GetWorkingDirectory + Returns: + (string) working directory + Description: + Returns the working directory of the engine. + + The working directory is the directory in which the engine is operating in, + and will always be in the same directory as the exe's if the engine was started normally. + But there are some cases where the working directory won't necessary be the same as the exe's, such as when the game is started via Steam. + + GetModuleName + Returns: + (string) module name + Description: + Returns the file name of the engine, without the extension. + + GetFileDirectoryFromModule + Arguments: + 1) (string) path + Returns: + (string) directory name + Description: + Returns the directory of the given file path, without the directory of the engine. + The given path does not need to actually exist. + + GetFileTopDirectory + Arguments: + 1) (string) path + Returns: + (string) directory name + Description: + Returns the topmost directory of the given file path. + The given path does not need to actually exist. + + GetFileName + Arguments: + 1) (string) path + Returns: + (string) file name + Description: + Returns the file name of the given file path. + The given path does not need to actually exist. + + GetFileNameWithoutExtension + Arguments: + 1) (string) path + Returns: + (string) file name + Description: + Returns the file name of the given file path, without its extension. + The given path does not need to actually exist. + + GetFileExtension + Arguments: + 1) (string) path + Returns: + (string) file extension + Description: + Returns the file extension of the given file path. + The given path does not need to actually exist. + + IsFileExists + Arguments: + 1) (string) path + Returns: + (bool) result + Description: + Returns true if the given file exists. + + IsDirectoryExists + Arguments: + 1) (string) path + Returns: + (bool) result + Description: + Returns true if the given directory exists. + + --------------------------------> Time <-------------------------------- + + GetSystemTimeMilliS + Returns: + (int) time + Description: + Returns the time of the system clock in milliseconds. + + GetSystemTimeNanoS + Returns: + (int) time + Description: + Returns the time of the system clock in nanoseconds. + + --------------------------------> Debugging <-------------------------------- + + WriteLog + Arguments: + 1+) (T) value... + Description: + Change. + + Writes the values of the given arguments to the LogWindow. + + RaiseMessageWindow + Arguments: + 1) (string) title text + 2) (string) description text + 3) (int) window flags + Returns: + (int) window result + Description: + Raises a message window similar to RaiseError, but does not terminate the script. + The game will be paused until the message window is addressed. The LogWindow will not be affected. + + For the list of window flags, refer to this page: + https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox + + The following flags are not allowed and will be automatically deleted: + MB_SETFOREGROUND + MB_DEFAULT_DESKTOP_ONLY + MB_SERVICE_NOTIFICATION + MB_SYSTEMMODAL + MB_TASKMODAL + The following flags are forced: + MB_APPLMODAL + + The return value is dependent on the user's interaction with the message window. + Refer to the same page for the list and explaination of return values. + + RaiseMessageWindow (Overload) + Arguments: + 1) (string) title text + 2) (string) description text + Returns: + (int) window result + Description: + Overloaded with 2 arguments. + + Triggers RaiseMessageWindow with MB_OK as the window flag value. + + --------------------------------> Common Data <-------------------------------- + + GetCommonData (Overload) + Arguments: + 1) (string) key + Returns: + (T) stored value + Description: + Overloaded with 1 argument. + + A variant of GetCommonData(key, default) where the "default value" argument is omitted. + A null value will be returned if the requested key-value pair does not exist. + + GetAreaCommonData (Overload) + Arguments: + 1) (string) area + 2) (string) key + Returns: + (T) stored value + Description: + Overloaded with 2 arguments. + + A variant of GetAreaCommonData(area, key, default) where the "default value" argument is omitted. + A null value will be returned if the requested key-value pair does not exist. + + DeleteWholeAreaCommonData + Arguments: + 1) (string) name + Description: + Deletes the whole area common data, not just the key-value list. + To use the area common data again, it must be recreated with CreateCommonDataArea. + + LoadCommonDataValuePointer + Arguments: + 1) (string) key + 2) (T) initial value + Returns: + (pointer) value pointer + Description: + Obtains a value pointer to the common data value in the default area. + + If the requested common data does not exist, it will be created and initialized with the provided value. + + LoadCommonDataValuePointer (Overload) + Arguments: + 1) (string) key + Returns: + (pointer) value pointer + Description: + Overloaded with 1 argument. + + Obtains a value pointer to the common data value in the default area. + + If the requested common data does not exist, a null pointer will be returned. + + LoadAreaCommonDataValuePointer + Arguments: + 1) (string) area + 2) (string) key + 3) (T) initial value + Returns: + (pointer) value pointer + Description: + Obtains a value pointer to the common data value in the given area. + + If the requested common data does not exist, it will be created and initialized with the provided value. + + LoadAreaCommonDataValuePointer (Overload) + Arguments: + 1) (string) area + 2) (string) key + Returns: + (pointer) value pointer + Description: + Overloaded with 1 argument. + + Obtains a value pointer to the common data value in the given area. + + If the requested common data does not exist, a null pointer will be returned. + + IsValidCommonDataValuePointer + Arguments: + 1) (pointer) value pointer + Returns: + (bool) valid + Description: + Returns if the given value is a valid common data value pointer. + + SetCommonDataPtr + Arguments: + 1) (pointer) value pointer + 2) (T) value + Description: + SetCommonData/SetAreaCommonData using pointers. + + The use of direct pointers mitigate the need for map traversals present in regular common data accesses, + and thus would remarkably improve speed. + Using an invalid pointer may cause a memory access violation. + + GetCommonDataPtr + Arguments: + 1) (pointer) value pointer + 2) (T) default value + Returns: + (T) stored value + Description: + GetCommonData/GetAreaCommonData using pointers. + + The use of direct pointers mitigate the need for map traversals present in regular common data accesses, + and thus would remarkably improve speed. + Using an invalid pointer may cause a memory access violation. + + GetCommonDataPtr (Overload) + Arguments: + 1) (pointer) value pointer + Returns: + (T) stored value + Description: + Overloaded with 1 argument. + + GetCommonData/GetAreaCommonData using pointers. + + The use of direct pointers mitigate the need for map traversals present in regular common data accesses, + and thus would remarkably improve speed. + Using an invalid pointer may cause a memory access violation. + + --------------------------------> Engine Utilities <-------------------------------- + + IsEngineFastMode + Returns: + (bool) result + Description: + Returns whether the engine is in the "fast mode" state. + (Note: Normally triggered with the LCtrl key.) + + GetConfigWindowSizeIndex + Returns: + (int) index + Description: + Returns the config's selected window size index. + + GetConfigWindowSizeList + Returns: + (int[][]) available window sizes + Description: + Returns an array of the window sizes specified in th_dnh.def. + + GetConfigVirtualKeyMapping + Arguments: + 1) (int) virtual key + Returns: + (int[2]) keys mapping + Description: + Returns the key mapping [keyboard, pad] as set in the config. + + Mappings will not change if keys are reassigned in-game. + + GetConfigWindowTitle + Returns: + (string) window title + Description: + Returns the engine's default window title, or the one specified in th_dnh.def if it exists. + + SetWindowTitle + Arguments: + 1) (string) window title + Description: + Sets the window title. + + Passing in an empty string will reset the window title to the default. + + SetEnableUnfocusedProcessing + Arguments: + 1) (bool) enables + Description: + Enables or disables unfocused processing. + + GetLastFrameUpdateSpeed + Returns: + (int) milliseconds + Description: + Returns the time the engine took to update scripts in the previous frame in milliseconds. + + GetLastFrameRenderSpeed + Returns: + (int) milliseconds + Description: + Returns the time the engine took to render the previous frame in milliseconds. + + --------------------------------> Stage Information <-------------------------------- + + SetScore + Arguments: + 1) (int) score + Description: + Sets the score value. + + SetGraze + Arguments: + 1) (int) graze + Description: + Sets the graze count. + + SetPoint + Arguments: + 1) (int) point + Description: + Sets the default point item value. + + --------------------------------> Archive <-------------------------------- + + AddArchiveFile (Overload) + Arguments: + 1) (string) path + 2) (int) offset + Returns: + (bool) load successful + Description: + Overloaded with 2 arguments. + + Loads a .dat archive, with the added capability to specify the read offset. + + GetArchiveFilePathList + Arguments: + 1) (string) path + 2) (bool) full path + Returns: + (string[]) paths + Description: + Lists out the stored file entries in the given .dat archive. + Archive must have already been loaded. + + --------------------------------> Screenshot <-------------------------------- + + SaveSnapShotA3 + Arguments: + 1) (string) path + 2) (int) rect left + 3) (int) rect top + 4) (int) rect right + 5) (int) rect bottom + 6) (const) format + Returns: + (bool) result + Description: + Renders the whole screen to a texture and saves the specified rectangular area of the texture to a file with the given name. + Returns true if the save was successful. + + Available formats: + IFF_BMP: Bitmap file. (.bmp) (default) + IFF_JPG: Joint Photographic Experts Group graphics file. (.jpeg) + IFF_TGA: TARGA bitmap file. (.tga) + IFF_PNG: Portable Network Graphics file. (.png) + IFF_DDS: DirectDraw Surface file. (.dds) + IFF_PPM: Portable PixelMap graphics file. (.ppm) + + --------------------------------> Script <-------------------------------- + + UnloadScript + Arguments: + 1) (int) script ID + Description: + Unloads a script that was loaded with LoadScript or LoadScriptInThread. + + UnloadScriptFromCache + Arguments: + 1) (string) script path + Description: + Unloads the given given from the script source cache. + + Does nothing if the script does not exist in the cache. + + StartScript (Overload) + Arguments: + 1) (int) script ID + 2) (bool) unload + Description: + Overloaded with 2 arguments. + + Starts the given script, and whether or not to remove the script from the "Loaded Scripts" cache. (NOT the "Script Source" cache) + A script that is often restarted would benefit from this overload by using LoadScript only once, + and then using StartScript(idScript, false) to avoid having to repeatedly call LoadScript. + + *StartScript(idScript) = StartScript(idScript, true) + + PauseScript + Arguments: + 1) (int) script ID + 2) (bool) pause + Description: + Pauses or unpauses the specified script. Not guaranteed to work flawlessly. + Causes an error is the script ID is the ID of the script from which the function was called, + aka; "a script cannot pause itself". + + GetScriptStatus + Arguments: + 1) (int) script ID + Returns: + (const) status + Description: + Returns the status of the specified script. + + Possible return values: + - STATUS_LOADING ; Script is currently loading. + - STATUS_LOADED ; Script has been loaded. + - STATUS_RUNNING ; Script is running. + - STATUS_PAUSED ; Script has been paused. + - STATUS_CLOSING ; Script is closing. + - STATUS_INVALID ; Any other cases, or invalid script ID. + + --------------------------------> Event <-------------------------------- + + GetEventArgumentCount + Returns: + (int) count + Description: + Returns the event argument count of the active event. + + NotifyEvent + Arguments: + 1) (int) script ID + 2) (int) event type + 3+) (T) arguments... + Returns: + (T) event result + Description: + Change. + + It is possible to pass as many event arguments as you want. + + *Scripts paused with PauseScript will still be able to run events. + + NotifyEventOwn + Arguments: + 1) (int) event type + 2+) (T) arguments... + Returns: + (T) event result + Description: + NotifyEvent's the script in which it was called. + + It is possible to pass as many event arguments as you want. + + *Scripts paused with PauseScript will still be able to run events. + + NotifyEventAll + Arguments: + 1) (int) event type + 2+) (T) arguments... + Description: + Change. + NotifyEvent's all actively running scripts. + + It is possible to pass as many event arguments as you want. + + *Scripts paused with PauseScript will still be able to run events. + + --------------------------------> Matrix <-------------------------------- + + A "matrix" here is a 16-member array representing a 4x4 matrix arranged row-by-row. + Ex: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] (The identity matrix) + A "vector" here is a float value array of the specified size. + Ex: [3, 4, 5] -> VECTOR3 + [5, 5, 0, 2] -> VECTOR4 + + MatrixIdentity + Returns: + (matrix) the identity matrix + Description: + Contructs an identity matrix. + + MatrixInverse + Arguments: + 1) (matrix) matrix + Returns: + (matrix) result + Description: + Inverses the given matrix. + + MatrixAdd + Arguments: + 1) (matrix) matrix1 + 2) (matrix) matrix2 + Returns: + (matrix) result + Description: + Adds two matrices together. + Note: Directly using the "+" operator also works. + + MatrixSubtract + Arguments: + 1) (matrix) matrix1 + 2) (matrix) matrix2 + Returns: + (matrix) result + Description: + Subtracts two matrices. + Note: Directly using the "-" operator also works. + + MatrixMultiply + Arguments: + 1) (matrix) matrix1 + 2) (matrix) matrix2 + Returns: + (matrix) result + Description: + Multiplies two matrices together. + + MatrixDivide + Arguments: + 1) (matrix) matrix1 + 2) (matrix) matrix2 + Returns: + (matrix) result + Description: + Divides two matrices. + + MatrixTranspose + Arguments: + 1) (matrix) matrix + Returns: + (matrix) result + Description: + Transposes the given matrix. + + MatrixDeterminant + Arguments: + 1) (matrix) matrix + Returns: + (float) result + Description: + Calculates the determinant of the given matrix. + + MatrixLookAtLH + Arguments: + 1) (VECTOR3) eye vector + 2) (VECTOR3) destination vector + 3) (VECTOR3) orientation vector + Returns: + (matrix) result + Description: + Constructs a left-handed look-at matrix. + + MatrixLookAtRH + Arguments: + 1) (VECTOR3) eye vector + 2) (VECTOR3) destination vector + 3) (VECTOR3) orientation vector + Returns: + (matrix) result + Description: + Constructs a right-handed look-at matrix. + + MatrixTransformVector + Arguments: + 1) (VECTOR3) position + 2) (matrix) transformation matrix + Returns: + (VECTOR4) result + Description: + Transforms the given (x, y, z, 1) point with the given matrix. + + --------------------------------> Screen Status <-------------------------------- + + GetMonitorWidth + Returns: + (int) monitor width + Description: + Returns the width of the primary display monitor. + + GetMonitorHeight + Returns: + (int) monitor height + Description: + Returns the height of the primary display monitor. + + GetScreenWidth + Returns: + (int) screen width + Description: + Returns the width of the engine screen. (specified in th_dnh.def as "screen.width") + + GetScreenHeight + Returns: + (int) screen height + Description: + Returns the height of the engine screen. (specified in th_dnh.def as "screen.height") + + GetWindowedWidth + Returns: + (int) window width + Description: + Returns the width of the windowed mode. + + GetWindowedHeight + Returns: + (int) window width + Description: + Returns the height of the windowed mode. + + IsFullscreenMode + Returns: + (bool) result + Description: + Returns whether or not the game is in fullscreen mode. + Both pseudo and true fullscreen modes register as true. + + --------------------------------> Sound <-------------------------------- + + SetSoundDivisionVolumeRate + Arguments: + 1) (const) division + 2) rate + Description: + Sets the volume rate of the given sound division. + The volume rates of all sound objects assigned to the division are multiplied by the division's rate. + + GetSoundDivisionVolumeRate + Arguments: + 1) (const) division + Returns: + (float) volume rate + Description: + Returns the volume rate of the given sound division. + + --------------------------------> Input <-------------------------------- + + GetVirtualKeyMapping + Arguments: + 1) (int) virtual key + Returns: + (int[2]) keys mapping + Description: + Returns the current key mapping [keyboard, pad]. + + --------------------------------> Resource Loading <-------------------------------- + + LoadTextureEx + Arguments: + 1) (string) path + 2) (bool) use mipmap + 3) (bool) use non-power-of-two + Returns: + (bool) loading result + Description: + Returns a boolean value of whether loading was successful. + + Loads a texture with more options. + Mipmap option generates a mipmap chain, causes textures to look better when scaled down when used with mipmap filtering. + Non-power-of-two option prevents blurring when the source texture's dimensions are not powers of two. (Due to DirectX's nature, may cause rendering to be slightly slower.) + + LoadTextureInLoadThreadEx + Arguments: + 1) (string) path + 2) (bool) use mipmap + 3) (bool) use non-power-of-two + Returns: + (bool) loading result + Description: + Returns a boolean value of whether initial loading was successful. + + LoadTextureEx in the load thread. + + LoadShader + Arguments: + 1) (string) path + Returns: + (bool) loading result + Description: + Loads a shader file, and returns a boolean value of whether loading was successful. + + RemoveShader + Arguments: + 1) (string) path + Description: + Removes a shader data that was previously loaded with LoadShader. + + LoadMesh + Arguments: + 1) (string) path + Returns: + (bool) loading result + Description: + Loads a mesh data file, and returns a boolean value of whether loading was successful. + + RemoveMesh + Arguments: + 1) (string) path + Description: + Removes a mesh data that was previously loaded with LoadMesh. + + --------------------------------> Render Target <-------------------------------- + + CreateRenderTargetEx + Arguments: + 1) (string) name + 2) (int) width + 3) (int) height + Returns: + (bool) creation result + Description: + Returns a boolean value of whether creation was successful. + + Creates a render target with the specified name, width, and height. + Fails if either value is not a positive integer. + + ClearRenderTargetA1 + Arguments: + 1) (string) name + Returns: + (bool) clear result + Description: + Previously [SetRenderTarget]. + + Returns a boolean value of whether the operation was successful. + + Clears the render target. + + ClearRenderTargetA2 + Arguments: + 1) (string) name + 2) (int) clear color red + 3) (int) clear color green + 4) (int) clear color blue + 5) (int) clear color alpha + Returns: + (bool) clear result + Description: + Returns a boolean value of whether the operation was successful. + + Clears the render target and fills it with the specified color and alpha. + + ClearRenderTargetA3 + Arguments: + 1) (string) name + 2) (int) clear color red + 3) (int) clear color green + 4) (int) clear color blue + 5) (int) clear color alpha + 6) (int) rect left + 7) (int) rect top + 8) (int) rect right + 9) (int) rect bottom + Returns: + (bool) clear result + Description: + Returns a boolean value of whether the operation was successful. + + Clears the render target in the specified rectangular area and fills that area with the specified color and alpha. + + SaveRenderedTextureA3 + Arguments: + 1) (string) name + 2) (string) path + 3) (int) rect left + 4) (int) rect top + 5) (int) rect right + 6) (int) rect bottom + 7) (const) format + Returns: + (bool) save result + Description: + SaveRenderedTextureA2, with the added ability of image format specification. + + Available formats are: + IFF_BMP: Bitmap file. (.bmp) (default) + IFF_JPG: Joint Photographic Experts Group graphics file. (.jpeg) + IFF_TGA: TARGA bitmap file. (.tga) + IFF_PNG: Portable Network Graphics file. (.png) + IFF_DDS: DirectDraw Surface file. (.dds) + IFF_PPM: Portable PixelMap graphics file. (.ppm) + + --------------------------------> Device Capabilities <-------------------------------- + + IsVertexShaderSupported + Arguments: + 1) (int) major + 2) (int) minor + Returns: + (bool) result + Description: + Checks if the video card on the device supports the given vertex shader version. + + --------------------------------> Fog <-------------------------------- + + SetFogParam (Overload) + Arguments: + 1) fog start + 2) fog end + 3) (int) fog hex color + Description: + Overloaded with 3 arguments. + + Sets the fog color as an XRGB hexadecimal color value. + + Example: + SetFogParam(0, 1024, 0xFF7B32); //-> SetFogParam(0, 1024, 255, 123, 50); + + --------------------------------> 3D Camera <-------------------------------- + + SetCameraMode + Arguments: + 1) (const) mode + Description: + Switches the 3D camera between available modes. + Modes: + CAMERA_NORMAL + - The normal 3D camera mode, positioned with elevation and azimuth angles. + CAMERA_LOOKAT + - The new 3D camera mode for maths enthusiasts, with the ability to directly specify camera position and view target position. + Configured with SetCameraFocusX/Y/Z or SetCameraPosEye and SetCameraPosLookAt. + + SetCameraPosEye + Arguments: + 1) x + 2) y + 3) z + Description: + Literally just SetCameraFocusXYZ with a different name. + + SetCameraPosLookAt + Arguments: + 1) x + 2) y + 3) z + Description: + Used with CAMERA_LOOKAT mode. + Sets the camera's "look-at" position. + + GetCameraViewMatrix + Returns: + (matrix) view matrix + Description: + Returns the 3D camera's view matrix. + + GetCameraProjectionMatrix + Returns: + (matrix) projection matrix + Description: + Returns the 3D camera's projection matrix. + + GetCameraViewProjectionMatrix + Returns: + (matrix) view-projection matrix + Description: + Returns the 3D camera's view-projection matrix. + + --------------------------------> Intersection <-------------------------------- + + IsIntersected_Point_Polygon + Arguments: + 1) point - x + 2) point - y + 3) (float[2][]) polygon vertices + Returns: + (bool) intersection + Description: + Returns true if the given point intersects with the polygon. + + The polygon can be convex, concave, or complex (self-intersecting). + + IsIntersected_Point_Circle + Arguments: + 1) point - x + 2) point - y + 3) circle - x + 4) circle - y + 5) circle - radius + Returns: + (bool) intersection + Description: + Returns true if the given point intersects with the circle. + + IsIntersected_Point_Ellipse + Arguments: + 1) point - x + 2) point - y + 3) ellipse - x + 4) ellipse - y + 5) ellipse - x radius + 6) ellipse - y radius + Returns: + (bool) intersection + Description: + Returns true if the given point intersects with the ellipse. + + IsIntersected_Point_Line + Arguments: + 1) point - x + 2) point - y + 3) line - start x + 4) line - start y + 5) line - end x + 6) line - end y + 7) line - width + Returns: + (bool) intersection + Description: + Returns true if the given point intersects with the line. + + IsIntersected_Point_RegularPolygon + Arguments: + 1) point - x + 2) point - y + 3) polygon - x + 4) polygon - y + 5) polygon - radius + 6) (int) polygon - edge count + 7) polygon - angle (degrees) + Returns: + (bool) intersection + Description: + Returns true if the given point intersects with the regular polygon. + + IsIntersected_Circle_Polygon + Arguments: + 1) circle - x + 2) circle - y + 3) circle - radius + 4) (float[2][]) polygon vertices + Returns: + (bool) intersection + Description: + Returns true if the given circle intersects with the polygon. + + The polygon can be convex, concave, or complex (self-intersecting). + + IsIntersected_Circle_Circle + Arguments: + 1) circle 1 - x + 2) circle 1 - y + 3) circle 1 - radius + 4) circle 2 - x + 5) circle 2 - y + 6) circle 2 - radius + Returns: + (bool) intersection + Description: + Returns true if the given circles intersect. + + IsIntersected_Circle_Ellipse + Arguments: + 1) circle - x + 2) circle - y + 3) circle - radius + 4) ellipse - x + 5) ellipse - y + 6) ellipse - x radius + 7) ellipse - y radius + Returns: + (bool) intersection + Description: + Returns true if the given circle intersects with the ellipse. + + IsIntersected_Circle_RegularPolygon + Arguments: + 1) circle - x + 2) circle - y + 3) circle - radius + 4) polygon - x + 5) polygon - y + 6) polygon - radius + 7) (int) polygon - edge count + 8) polygon - angle (degrees) + Returns: + (bool) intersection + Description: + Returns true if the given circle intersects with the regular polygon. + + IsIntersected_Line_Polygon + Arguments: + 1) line - start x + 2) line - start y + 3) line - end x + 4) line - end y + 5) line - width + 6) (float[2][]) polygon vertices + Returns: + (bool) intersection + Description: + Returns true if the given line intersects with the polygon. + + The polygon can be convex, concave, or complex (self-intersecting). + + IsIntersected_Line_Circle + Arguments: + 1) line - start x + 2) line - start y + 3) line - end x + 4) line - end y + 5) line - width + 6) circle - x + 7) circle - y + 8) circle - radius + Returns: + (bool) intersection + Description: + Returns true if the given line intersects with the circle. + + IsIntersected_Line_Ellipse + Arguments: + 1) line - start x + 2) line - start y + 3) line - end x + 4) line - end y + 5) line - width + 6) ellipse - x + 7) ellipse - y + 8) ellipse - x radius + 9) ellipse - y radius + Returns: + (bool) intersection + Description: + Returns true if the given line intersects with the ellipse. + + IsIntersected_Line_Line + Arguments: + 1) line 1 - start x + 2) line 1 - start y + 3) line 1 - end x + 4) line 1 - end y + 5) line 1 - width + 6) line 2 - start x + 7) line 2 - start y + 8) line 2 - end x + 9) line 2 - end y + 10) line 2 - width + Returns: + (bool) intersection + Description: + Returns true if the given lines intersect. + + IsIntersected_Line_RegularPolygon + Arguments: + 1) line - start x + 2) line - start y + 3) line - end x + 4) line - end y + 5) line - width + 6) polygon - x + 7) polygon - y + 8) polygon - radius + 9) (int) polygon - edge count + 10) polygon - angle (degrees) + Returns: + (bool) intersection + Description: + Returns true if the given line intersects with the regular polygon. + + IsIntersected_Polygon_Polygon + Arguments: + 1) (float[2][]) polygon 1 vertices + 2) (float[2][]) polygon 2 vertices + Returns: + (bool) intersection + Description: + Returns true if the given polygons intersect. + + The polygons can be convex, concave, or complex (self-intersecting). + + IsIntersected_Polygon_Ellipse + Arguments: + 1) (float[2][]) polygon vertices + 2) ellipse - x + 3) ellipse - y + 4) ellipse - x radius + 5) ellipse - y radius + Returns: + (bool) intersection + Description: + Returns true if the given polygon intersects with the ellipse. + + The polygon can be convex, concave, or complex (self-intersecting). + + IsIntersected_Polygon_RegularPolygon + Arguments: + 1) (float[2][]) polygon 1 vertices + 2) polygon 2 - x + 3) polygon 2 - y + 4) polygon 2 - radius + 5) (int) polygon 2 - edge count + 6) polygon 2 - angle (degrees) + Returns: + (bool) intersection + Description: + Returns true if the given polygon intersects with the regular polygon. + + The polygon can be convex, concave, or complex (self-intersecting). + + --------------------------------> Color Utility <-------------------------------- + + ColorARGBToHex + Arguments: + 1) (int) alpha + 2) (int) red + 3) (int) green + 4) (int) blue + Returns: + (int) hex color + Description: + Returns an ARGB hexadecimal color value of the given colors. + + Example: + ColorARGBToHex(255, 255, 255, 255); + //Result: 0xFFFFFFFF + + ColorARGBToHex(67, 255, 0, 125); + //Result: 0x43FF007D + + ColorARGBToHex (Overload) + Arguments: + 1) (int[4]) color + Returns: + (int) hex color + Description: + Overloaded with 1 argument. + + Returns ColorARGBToHex(color[0], color[1], color[2], color[3]); + + ColorHexToARGB + Arguments: + 1) (int) hex color + Returns: + (int[4]) ARGB color + Description: + Returns an ARGB color array of the given hexadecimal color (D3DCOLOR). + + Example: + ColorHexToARGB(0xFFFFFFFF); + //Result: [255, 255, 255, 255] + + ColorHexToARGB(0x43FF007D); + //Result: [67, 255, 0, 125] + + ColorHexToARGB (Overload) + Arguments: + 1) (int) hex color + 2) (int) control + Returns: + (int[]) color array + Description: + Overloaded with 2 arguments. + + Returns an ARGB color array of the given hexadecimal color (D3DCOLOR), controlled by the control argument. + + The control value dictates which color channels to output, and in which order. + The bit format is: + MSB LSB (16 bit) + 000000 00 00 00 00 00 + Unused Count 1st 2nd 3rd 4th + + - Bits 0-5 are unused. + - Bits 6-7 control the amount of color channels to return, subtracted by 1. + (11 is 4 channels, 10 is 3, 01 is 2, 00 is 1) + - Bits 8-15 control the order of the color channels, duplication is allowed. + 00 (0) signifies the A channel. + 01 (1) signifies the R channel. + 10 (2) signifies the G channel. + 11 (3) signifies the B channel. + + Examples: + 0b1100011011 (0x31b) -> [A, R, G, B] + 0b1101101100 (0x36c) -> [R, G, B, A] + 0b1100000000 (0x300) -> [A, A, A, A] + 0b1001101100 (0x26c) -> [R, G, B] + 0b0001000000 (0x040) -> [R] + + For people whose brain lacks the required amount of sanity (or lack thereof) to understand the control argument, here are some constants: + COLOR_PERMUTE_ARGB + COLOR_PERMUTE_RGBA + COLOR_PERMUTE_BGRA + COLOR_PERMUTE_RGB + COLOR_PERMUTE_BGR + COLOR_PERMUTE_A + COLOR_PERMUTE_R + COLOR_PERMUTE_G + COLOR_PERMUTE_B + + Example: + ColorHexToARGB(0xFFFFFFFF, 0x31b); + //Result: [255, 255, 255, 255] + + ColorHexToARGB(0xFFFFFFFF, 0x000); + //Result: [255] + + ColorHexToARGB(0x43FF007D, 0x31b) + //Result: [67, 255, 0, 125] + + ColorHexToARGB(0x43FF007D, 0x36c); + //Result: [255, 0, 125, 67] + + ColorHexToARGB(0x43FF007D, 0x2e4); + //Result: [125, 0, 255] + + ColorRGBtoHSV + Arguments: + 1) (int) red + 2) (int) green + 3) (int) blue + Returns: + (int[3]) color array + Description: + Returns the given RGB color as a HSV color array. + + ColorHexRGBtoHSV + Arguments: + 1) (int) hex color + Returns: + (int[3]) color array + Description: + Returns the given XRGB hexadecimal color as a HSV color array. + + ColorHSVtoRGB + Arguments: + 1) (int) hue + 2) (int) saturation + 3) (int) value + Returns: + (int[3]) color array + Description: + Returns the given HSV color as an RGB color array. + + ColorHSVtoHexRGB + Arguments: + 1) (int) hue + 2) (int) saturation + 3) (int) value + Returns: + (int) hex color + Description: + Returns the given HSV color as an XRGB hexadecimal color. + + --------------------------------> Base Object Functions <-------------------------------- + + SetInvalidPositionReturn + Arguments: + 1) x + 2) y + Description: + Sets the default position that position-fetching functions will return if the object does not exist. + + The default value is (0, 0). + + GetObjectDistance + Arguments: + 1) (int) object 1 ID + 2) (int) object 2 ID + Returns: + (float) distance + Description: + Change. + + The Z positions will not be included in the calculation if neither objects are 3D-valid. + + GetObjectDistanceSq + Arguments: + 1) (int) object 1 ID + 2) (int) object 2 ID + Returns: + (float) distance + Description: + Returns the square of the distance between two objects. + + The Z positions will not be included in the calculation if neither objects are 3D-valid. + + GetObjectDeltaAngle + Arguments: + 1) (int) object 1 ID + 2) (int) object 2 ID + Returns: + (float) angle + Description: + Returns the angle between two objects. + + The Z positions will not be included in the calculation if neither objects are 3D-valid. + + Obj_GetValueI + Arguments: + 1) (int) object ID + 2) (int) key + Returns: + (T) value + Description: + Obj_GetValue with int value key. + + Obj_GetValueDI + Arguments: + 1) (int) object ID + 2) (int) key + 3) default + Returns: + (T) value + Description: + Obj_GetValueD with int value key. + + Obj_SetValueI + Arguments: + 1) (int) object ID + 2) (int) key + 3) value + Returns: + (T) value + Description: + Obj_SetValue with int value key. + + Obj_DeleteValueI + Arguments: + 1) (int) object ID + 2) (int) key + Returns: + (T) value + Description: + Obj_DeleteValue with int value key. + + Obj_IsValueExistsI + Arguments: + 1) (int) object ID + 2) (int) key + Returns: + (T) value + Description: + Obj_IsValueExists with int value key. + + Obj_GetValueCount + Arguments: + 1) (int) object ID + Returns: + (int) count + Description: + Returns the number of stored values in the object's string-indexed value table. + + Obj_GetValueCountI + Arguments: + 1) (int) object ID + Returns: + (int) count + Description: + Returns the number of stored values in the object's int-indexed value table. + + Obj_CopyValueTable + Arguments: + 1) (int) destination object ID + 2) (int) source object ID + 3) (int) mode + Returns: + (int) source object's object value amount + Description: + Copies the source's object value table to the destination's object value table. + + Available modes: + 0 - Object value table is cleared before the copy. + 1 - Value will be overwritten in case of key conflicts. + 2 - Value will not be overwritten in case of key conflicts. + + --------------------------------> Shader Object Functions <-------------------------------- + + ObjShader_SetShaderT + Arguments: + 1) (int) object ID + 2) (string) shader name + 2) (string) shader source + Returns: + (bool) success + Description: + Compiles a shader from the given string. Returns whether the operation was successful. + Shader name should be unique. + + --------------------------------> Render Object Functions <-------------------------------- + + [---------------------------> Blending <---------------------------] + + ObjRender_SetBlendType + Description: + Addition. + + BLEND_ALPHA_INV - Alpha blending with source color inversion. + + [---------------------------> Scale <---------------------------] + + ObjRender_SetScaleXYZ (Overload) + Arguments: + 1) (int) object ID + 2) scale + Description: + Overloaded with 2 arguments. + + Sets the object's XYZ scale. + + Example: + ObjRender_SetScaleXYZ(obj, 2); //-> ObjRender_SetScaleXYZ(obj, 2, 2, 2); + + [---------------------------> Color & Alpha <---------------------------] + + ObjRender_SetColor (Overload) + Arguments: + 1) (int) object ID + 2) (int) hex color + Description: + Overloaded with 2 arguments. + + Sets the object's color as an XRGB hexadecimal color value. + + Example: + ObjRender_SetColor(obj, 0xFF7B32); //-> ObjRender_SetColor(obj, 255, 123, 50); + + ObjRender_SetColorHSV + Arguments: + 1) (int) object ID + 2) (int) color hue + 3) (int) color saturation + 4) (int) color value + Description: + Sets the object's RGB color as a HSV color. + + ObjRender_GetColor + Arguments: + 1) (int) object ID + Returns: + (int[3]) color + Description: + Returns an [r, g, b] array of the object's color. + + ObjRender_GetColorHex + Arguments: + 1) (int) object ID + Returns: + (int) hex color + Description: + Returns the object's color an XRGB hexadecimal color value. + + ObjRender_GetAlpha + Arguments: + 1) (int) object ID + Returns: + (int) alpha + Description: + Returns the object's alpha value. + + [---------------------------> Texture Filtering <---------------------------] + + ObjRender_SetTextureFilterMin + Arguments: + 1) (int) object ID + 2) (const) mode + Description: + Sets the minification filtering mode for the render object. + + Filtering modes: + FILTER_NONE + FILTER_POINT + FILTER_LINEAR + FILTER_ANISOTROPIC + + Default is FILTER_LINEAR. + + ObjRender_SetTextureFilterMag + Arguments: + 1) (int) object ID + 2) (const) mode + Description: + Sets the magnification filtering mode for the render object. + + Default is FILTER_LINEAR. + + ObjRender_SetTextureFilterMip + Arguments: + 1) (int) object ID + 2) (const) mode + Description: + Sets the mipmap filtering mode for the render object. + + Default is FILTER_NONE. + + ObjRender_SetTextureFilter + Arguments: + 1) (int) object ID + 2) (const) filter min + 3) (const) filter mag + 4) (const) filter mip + Description: + Fused ObjRender_SetTextureFilterMin+Mag+Mip. + + [---------------------------> Vertex Shader <---------------------------] + + ObjRender_SetVertexShaderRenderingMode + Arguments: + 1) (int) object ID + 2) (bool) use vertex shader mode + Description: + Sets whether the render object will be rendered with support for vertex shaders. + Default is false. + + Rendering will not be performed without an attached shader object when this is set to true. + When using vertex shader rendering mode with 3D objects, fog must be manually computed with the shader. + + ObjRender_SetEnableDefaultTransformMatrix + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + Sets whether the render object will calculate its transformation matrix. + Default is true. + + The transformation matrix contains the object's scale, angle, and position data, along with the 2D camera matrix. + If set to false, the transformation matrix will only contain the 2D camera matrix. + + [---------------------------> Lighting <---------------------------] + + ObjRender_SetLightingEnable + Arguments: + 1) (int) object ID + 2) (bool) lighting enable + 2) (bool) specular lighting enable + Description: + Enables or disables the 3D directional lighting and specular lighting for the render object. + + The default values are false and false. + For mesh objects, the default values are true and false. + + If it is not necessary, I recommend you not use specular lighting, as it's quite computationally expensive. + + ObjRender_SetLightingDiffuseColor + Arguments: + 1) (int) object ID + 2) (int) r + 3) (int) g + 4) (int) b + Description: + Sets the diffuse color of the lighting. + + The default color value is (128, 128, 128). + + ObjRender_SetLightingDiffuseColor (Overload) + Arguments: + 1) (int) object ID + 2) (int) hex color + Description: + Overloaded with 2 arguments. + + Sets the object's diffuse lighting color as an XRGB hexadecimal color value. + + ObjRender_SetLightingSpecularColor + Arguments: + 1) (int) object ID + 2) (int) r + 3) (int) g + 4) (int) b + Description: + Sets the specular color of the lighting. + + The default color value is (0, 0, 0). + + ObjRender_SetLightingSpecularColor (Overload) + Arguments: + 1) (int) object ID + 2) (int) hex color + Description: + Overloaded with 2 arguments. + + Sets the object's specular lighting color as an XRGB hexadecimal color value. + + ObjRender_SetLightingAmbientColor + Arguments: + 1) (int) object ID + 2) (int) r + 3) (int) g + 4) (int) b + Description: + Sets the ambient color of the lighting. + + The default color value is (128, 128, 128). + + ObjRender_SetLightingAmbientColor (Overload) + Arguments: + 1) (int) object ID + 2) (int) hex color + Description: + Overloaded with 2 arguments. + + Sets the object's ambient lighting color as an XRGB hexadecimal color value. + + ObjRender_SetLightingDirection + Arguments: + 1) (int) object ID + 2) x component + 3) y component + 4) z component + Description: + Sets the direction vector of the lighting. + Vector does not need to be normalized, but should have a non-zero length. + + The default direction vector is (-1, -1, -1). + + --------------------------------> Primitive Object Functions <-------------------------------- + + ObjPrim_GetTexture + Arguments: + 1) (int) object ID + Returns: + (string) texture name + Description: + Returns the path/name of the primitive object's texture. + + ObjPrim_SetVertexColor (Overload) + Arguments: + 1) (int) object ID + 2) (int) vertex index + 3) (int) hex color + Description: + Overloaded with 3 arguments. + + Sets the vertex color as an XRGB hexadecimal color value. + + ObjPrim_SetVertexColorHSV + Arguments: + 1) (int) object ID + 2) (int) vertex index + 3) color hue + 4) color saturation + 5) color value + Description: + Sets the vertex color of the primitive object as a HSV color. + + ObjPrim_GetVertexColor + Arguments: + 1) (int) object ID + 2) (int) vertex index + Returns: + (int[3]) color + Description: + Returns the vertex color as an [r, g, b] array. + + ObjPrim_GetVertexColorHex + Arguments: + 1) (int) object ID + 2) (int) vertex index + Returns: + (int) hex color + Description: + Returns the vertex color as an XRGB hexadecimal color value. + + ObjPrim_GetVertexAlpha + Arguments: + 1) (int) object ID + 2) (int) vertex index + Returns: + (int) alpha + Description: + Returns the vertex alpha value. + + ObjPrim_SetVertexIndex + Arguments: + 1) (int) object ID + 2) (int[]) indices + Description: + Sets vertex indices to the primitive object. + Required for particle list objects. + + Example: + ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLELIST); + ObjPrim_SetVertexCount(obj, 4); + ObjPrim_SetVertexPosition(obj, 0, 0, 0); + ObjPrim_SetVertexPosition(obj, 1, 32, 0); + ObjPrim_SetVertexPosition(obj, 2, 0, 32); + ObjPrim_SetVertexPosition(obj, 3, 32, 32); + ObjPrim_SetVertexIndex(obj, [0, 1, 2, 1, 2, 3]); + + --------------------------------> 2D Sprite Object Functions <-------------------------------- + + ObjSprite2D_SetSourceRect (overload) + Arguments: + 1) (int) object ID + 2) (int[4]) rect + Description: + Overloaded with 2 arguments. + + ObjSprite2D_SetSourceRect(obj, rect[0], rect[1], rect[2], rect[3]); + + ObjSprite2D_SetDestRect (overload) + Arguments: + 1) (int) object ID + 2) (float[4]) rect + Description: + Overloaded with 2 arguments. + + ObjSprite2D_SetDestRect(obj, rect[0], rect[1], rect[2], rect[3]); + + --------------------------------> 2D Sprite List Object Functions <-------------------------------- + + ObjSpriteList2D_SetSourceRect (overload) + Arguments: + 1) (int) object ID + 2) (int[4]) rect + Description: + Overloaded with 2 arguments. + + ObjSpriteList2D_SetSourceRect(obj, rect[0], rect[1], rect[2], rect[3]); + + ObjSpriteList2D_SetDestRect (overload) + Arguments: + 1) (int) object ID + 2) (float[4]) rect + Description: + Overloaded with 2 arguments. + + ObjSpriteList2D_SetDestRect(obj, rect[0], rect[1], rect[2], rect[3]); + + ObjSpriteList2D_SetAutoClearVertexCount + Arguments: + 1) (int) object ID + 2) (bool) clear + Description: + Sets whether the 2D sprite list object will clear its vertices upon rendering. + + --------------------------------> 3D Sprite Object Functions <-------------------------------- + + ObjSprite3D_SetSourceRect (overload) + Arguments: + 1) (int) object ID + 2) (int[4]) rect + Description: + Overloaded with 2 arguments. + + ObjSprite3D_SetSourceRect(obj, rect[0], rect[1], rect[2], rect[3]); + + ObjSprite3D_SetDestRect (overload) + Arguments: + 1) (int) object ID + 2) (float[4]) rect + Description: + Overloaded with 2 arguments. + + ObjSprite3D_SetDestRect(obj, rect[0], rect[1], rect[2], rect[3]); + + ObjSprite3D_SetSourceDestRect (overload) + Arguments: + 1) (int) object ID + 2) (float[4]) rect + Description: + Overloaded with 2 arguments. + + ObjSprite3D_SetSourceDestRect(obj, rect[0], rect[1], rect[2], rect[3]); + + --------------------------------> Particle List Object Functions <-------------------------------- + + ObjParticleList_Create + Arguments: + 1) (const) type + Description: + Creates a new particle list object and returns its ID. + Available types are: + OBJ_PARTICLE_LIST_2D + OBJ_PARTICLE_LIST_3D + Vertex shader rendering is always on, and rendering will fail if an improper custom shader is used. + Not using a custom shader will result in the default shader being used. + + ObjParticleList_SetPosition + Arguments: + 1) (int) object ID + 2) X position + 3) Y position + 4) Z position + Description: + Sets the instance position data. + + ObjParticleList_SetScaleX + Arguments: + 1) (int) object ID + 2) X scale + Description: + Sets the instance X scale data. + + ObjParticleList_SetScaleY + Arguments: + 1) (int) object ID + 2) Y scale + Description: + Sets the instance Y scale data. + + ObjParticleList_SetScaleZ + Arguments: + 1) (int) object ID + 2) Z scale + Description: + Sets the instance Z scale data. + + ObjParticleList_SetScale + Arguments: + 1) (int) object ID + 2) X scale + 3) Y scale + 4) Z scale + Description: + Sets the instance scale data. + + ObjParticleList_SetScale (Overload) + Arguments: + 1) (int) object ID + 2) scale + Description: + Overloaded with 2 arguments. + + Sets the instance scale data. + + ObjParticleList_SetScale(obj, 2); //-> ObjParticleList_SetScale(obj, 2, 2, 2); + + ObjParticleList_SetAngleX + Arguments: + 1) (int) object ID + 2) X angle + Description: + Sets the instance X angle data. + + ObjParticleList_SetAngleY + Arguments: + 1) (int) object ID + 2) Y angle + Description: + Sets the instance Y angle data. + + ObjParticleList_SetAngleZ + Arguments: + 1) (int) object ID + 2) Z angle + Description: + Sets the instance Z angle data. + + ObjParticleList_SetAngleXYZ + Arguments: + 1) (int) object ID + 2) X angle + 3) Y angle + 3) Z angle + Description: + Sets the instance XYZ angle data. + + ObjParticleList_SetColor + Arguments: + 1) (int) object ID + 2) (int) red + 3) (int) green + 4) (int) blue + Description: + Sets the instance RGB color data. + + ObjParticleList_SetColor (Overload) + Arguments: + 1) (int) object ID + 2) (int) hex color + Description: + Overloaded with 2 arguments. + + Sets the instance color data as an XRGB hexadecimal color value. + + ObjParticleList_SetAlpha + Arguments: + 1) (int) object ID + 2) (int) alpha + Description: + Sets the instance alpha data. + + ObjParticleList_SetExtraData + Arguments: + 1) (int) object ID + 2) data 1 + 2) data 2 + 2) data 3 + Description: + Sets instance extra data. + These can be freely utilized by the scripters in case a custom shader is used. + + ObjParticleList_AddInstance + Arguments: + 1) (int) object ID + Description: + Submits the current data to the next instance. + + ObjParticleList_ClearInstance + Arguments: + 1) (int) object ID + Description: + Clears all previously submitted instance data of the current frame. + + --------------------------------> Mesh Object Functions <-------------------------------- + + ObjMesh_SetColor (Overload) + Arguments: + 1) (int) object ID + 2) (int) hex color + Description: + Overloaded with 2 arguments. + + Sets the mesh object's color as an XRGB hexadecimal color value. + + --------------------------------> Text Object Functions <-------------------------------- + + ObjText_GetText + Arguments: + 1) (int) object ID + Returns: + (string) text + Description: + Returns the text of the text object. + + ObjText_SetFixedWidth + Arguments: + 1) (int) object ID + 2) (int) width + Description: + Activates and sets the width of monospacing mode for the text object. + + If width is <= 0, the spacing mode returns to regular dynamic spacing. + + ObjText_SetFontWeight + Arguments: + 1) (int) object ID + 2) (int) weight + Description: + Sets the font weight for the following text object. + + Weight ranges from 0 to 1000, with 0 being the lightest and 1000 being the thickest. -1 for the default weight. + Some fonts may not support all weight values. + + *ObjText_SetFontBold(a, b) is equivalent to ObjText_SetFontWeight(a, b ? 700 : 400). + + ObjText_SetFontCharacterSet + Arguments: + 1) (int) object ID + 2) (int) charset + Description: + Sets the charset for the following text object. + + The following constants are defined: + CHARSET_ANSI + CHARSET_DEFAULT + CHARSET_SHIFTJIS + CHARSET_HANGUL + CHARSET_JOHAB + CHARSET_CHINESEBIG5 + CHARSET_TURKISH + CHARSET_VIETNAMESE + CHARSET_HEBREW + CHARSET_ARABIC + CHARSET_THAI + + For the full list of all charset values, refer to here: + https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/0d0b32ac-a836-4bd2-a112-b6000a1b4fc9 + Avoid using CHARSET_DEFAULT, as it may be device-dependent. + + To ensure that font glyphs generate correctly, match the text object's charset with the font's charset. + *The font charset is reset to either CHARSET_ANSI or CHARSET_SHIFTJIS every time ObjText_SetFontType is used. + + ObjText_SetFontColorTop (Overload) + Arguments: + 1) (int) object ID + 2) (int) hex color + Description: + Overloaded with 2 arguments. + + Sets the text object's font's top color as an XRGB hexadecimal color value. + + ObjText_SetFontColorBottom (Overload) + Arguments: + 1) (int) object ID + 2) (int) hex color + Description: + Overloaded with 2 arguments. + + Sets the text object's font's bottom color as an XRGB hexadecimal color value. + + ObjText_SetFontBorderColor (Overload) + Arguments: + 1) (int) object ID + 2) (int) hex color + Description: + Overloaded with 2 arguments. + + Sets the text object's font's border color as an XRGB hexadecimal color value. + + ObjText_SetVertexColor (Overload) + Arguments: + 1) (int) object ID + 2) (int) hex color + Description: + Overloaded with 2 arguments. + + Sets the text object's color as an ARGB hexadecimal color value. + + --------------------------------> Sound Object Functions <-------------------------------- + + ObjSound_SetResumeEnable + Arguments: + 1) (int) object ID + 2) (bool) resume enable + Description: + Formerly ObjSound_SetRestartEnable. + Function unchanged. + + If set to true, using ObjSound_Play on the sound object that was previously stopped with ObjSound_Stop will resume playing where it last left off. + + ObjSound_Seek + Arguments: + 1) (int) object ID + 2) time + Description: + Seeks to the specified time in the audio. + + ObjSound_SeekSampleCount + Arguments: + 1) (int) object ID + 2) (int) sample + Description: + Seeks to the specified sample in the audio. + + ObjSound_SetFrequency + Arguments: + 1) (int) object ID + 2) (int) frequency + Description: + Sets the frequency of the audio in sample rate. + Can be used to increase or decrease play speed. + + An input of 0 will reset the value to the audio's original frequency. + + ObjSound_GetInfo + Arguments: + 1) (int) object ID + 2) (const) type + Returns: + [varies] + Description: + Returns the value of the requested information about the sound object. + + List of available information types: + INFO_FORMAT + - The format of the audio file. + - SOUND_UNKNOWN + - SOUND_WAVE + - SOUND_OGG + - SOUND_MP3 + - SOUND_AWAVE + - SOUND_MIDI + INFO_CHANNEL + - The number of channels. + INFO_SAMPLE_RATE + - The sample rate of the audio in hertz. + - ObjSound_SetFrequency does not affect this value. + INFO_AVG_BYTE_PER_SEC + - The average byte per one second of audio. + INFO_BLOCK_ALIGN + - The block align. (channel * bytePerSample) + INFO_BIT_PER_SAMPLE + - The bits per sample of the audio. + INFO_POSITION + - The current reading position of the audio in seconds. + INFO_POSITION_SAMPLE + - The current reading position of the audio in sample count. + INFO_LENGTH + - The total length of the audio in seconds. + INFO_LENGTH_SAMPLE + - The total length of the audio in sample count. + + --------------------------------> Text File Object Functions <-------------------------------- + + ObjFileT_SetLineText + Arguments: + 1) (int) object ID + 2) (int) line number + 3) (string) new text + Description: + Sets the text of the given line of the text file object. + + *Note that the actual file content is only updated upon calling ObjFile_Store. + + --------------------------------> Binary File Object Functions <-------------------------------- + + ObjFileB_GetLastRead + Arguments: + 1) (int) object ID + Returns: + (int) result + Description: + Returns the amount of bytes read at the last read operation. + + A result of 0 may indicate an end-of-file. + + ObjFileB_ReadBoolean + Arguments: + 1) (int) object ID + Returns: + (bool) result + Description: + Change. + No longer throws an error upon attempting to read past the end-of-file. + + Reads a boolean value from the binary file object. + Advances the read pointer by 1. + + ObjFileB_ReadByte + Arguments: + 1) (int) object ID + Returns: + (int) result + Description: + Change. + No longer throws an error upon attempting to read past the end-of-file. + + Reads a byte value from the binary file object. + Advances the read pointer by 1. + + ObjFileB_ReadShort + Arguments: + 1) (int) object ID + Returns: + (int) result + Description: + Change. + No longer throws an error upon attempting to read past the end-of-file. + + Reads a short integer value from the binary file object. + Advances the read pointer by 2. + + ObjFileB_ReadInteger + Arguments: + 1) (int) object ID + Returns: + (int) result + Description: + Change. + No longer throws an error upon attempting to read past the end-of-file. + + Reads an integer value from the binary file object. + Advances the read pointer by 4. + + ObjFileB_ReadLong + Arguments: + 1) (int) object ID + Returns: + (int) result + Description: + Change. + No longer throws an error upon attempting to read past the end-of-file. + + Reads a long integer value from the binary file object. + Advances the read pointer by 8. + + ObjFileB_ReadFloat + Arguments: + 1) (int) object ID + Returns: + (float) result + Description: + Change. + No longer throws an error upon attempting to read past the end-of-file. + + Reads a single-precision float value from the binary file object. + Advances the read pointer by 4. + + ObjFileB_ReadDouble + Arguments: + 1) (int) object ID + Returns: + (float) result + Description: + Change. + No longer throws an error upon attempting to read past the end-of-file. + + Reads a double-precision float value from the binary file object. + Advances the read pointer by 8. + + ObjFileB_WriteBoolean + Arguments: + 1) (int) object ID + 2) (bool) value + Returns: + (int) bytes written + Description: + Writes a boolean value to the binary file object at the current write pointer. + Advances the write pointer by 1. + + ObjFileB_WriteByte + Arguments: + 1) (int) object ID + 2) (int) value + Returns: + (int) bytes written + Description: + Writes a boolean value to the binary file object at the current write pointer. + Advances the write pointer by 1. + + ObjFileB_WriteShort + Arguments: + 1) (int) object ID + 2) (int) value + Returns: + (int) bytes written + Description: + Writes a short integer value to the binary file object at the current write pointer. + Advances the write pointer by 2. + + ObjFileB_WriteInteger + Arguments: + 1) (int) object ID + 2) (int) value + Returns: + (int) bytes written + Description: + Writes an integer value to the binary file object at the current write pointer. + Advances the write pointer by 4. + + ObjFileB_WriteLong + Arguments: + 1) (int) object ID + 2) (int) value + Returns: + (int) bytes written + Description: + Writes a long integer value to the binary file object at the current write pointer. + Advances the write pointer by 8. + + ObjFileB_WriteFloat + Arguments: + 1) (int) object ID + 2) value + Returns: + (int) bytes written + Description: + Writes a single-precision float value to the binary file object at the current write pointer. + Advances the write pointer by 4. + + ObjFileB_WriteDouble + Arguments: + 1) (int) object ID + 2) value + Returns: + (int) bytes written + Description: + Writes a double-precision float value to the binary file object at the current write pointer. + Advances the write pointer by 8. + +----------------------------------------------> [Stage Script] <---------------------------------------------- + + --------------------------------> Basic Stage Functions <-------------------------------- + + SetStgFrame (Overload) + Arguments: + 1) (int) frame left + 2) (int) frame top + 3) (int) frame right + 4) (int) frame bottom + 5) (int) STG frame render priority - starting (inclusive) + 6) (int) STG frame render priority - ending (exclusive) + 7) (int) 2D camera render priority + Description: + Overloaded with 7 arguments. + + Additional ability to change the render priority of the 2D camera. + + SetIntersectionVisualization + Arguments: + 1) (bool) enable + Description: + Enables active visualization of all intersection object hitboxes. + + Color codes: + Green : Player hitbox+grazebox + Blue : Player shot + Cyan : Player spell + Yellow : Enemy hitbox+killbox + Red : Enemy shot + + SetIntersectionVisualizationRenderPriority + Arguments: + 1) (int) render priority + Description: + Sets the render priority of hitbox visualizations. + + Default value is 68. (GetCameraFocusPermitPriorityI() - 1) + + --------------------------------> Player Functions <-------------------------------- + + GetPlayerScriptID + Returns: + (int) script ID + Description: + Returns the script ID of the player object. + + GetPlayerAutoItemCollectLine + Returns: + (float) position + Description: + Returns the position of the player's item autocollection line. + + SetPlayerItemScope + Arguments: + 1) (int) value + Description: + Sets the player's item collection scope radius. + Effect equivalent to CollectItemsInCircle. + + GetPlayerItemScope + Returns: + (float) scope size + Description: + Gets the player's item collection scope radius. + + SetPlayerInvincibleGraze + Arguments: + 1) (bool) enable + Description: + Sets whether the player can graze during invincbility period. + True by default. All hail ZUN's engine. + + SetPlayerIntersectionEraseShot + Arguments: + 1) (bool) enable + Description: + Sets whether shots colliding with the player would get automatically deleted. + True by default. All hail ZUN's engine. Again. LOUDER! + + SetPlayerStateEndEnable + Arguments: + 1) (bool) enable + Description: + Sets whether STATE_END is permitted to activate. + If set to false, player life will continue below 0 upon each death without limit. + False by default if the main script is a package script. + + SetPlayerShootdownEventEnable + Arguments: + 1) (bool) enable + Description: + Sets whether EV_PLAYER_SHOOTDOWN will be notified upon the player's death. + Setting it to false would also disable STATE_DOWN and STATE_END from ever occuring. + + SetPlayerRebirthPosition + Arguments: + 1) x + 2) y + Description: + Sets the respawn point of the player. + Use REBIRTH_DEFAULT in either position to reset it to its default value. + + --------------------------------> Enemy Functions <-------------------------------- + + SetEnemyAutoDeleteClip + Arguments: + 1) (int) left + 2) (int) top + 3) (int) right + 4) (int) bottom + Description: + Sets the margin that enemy objects are allowed to traverse past the edges of the STG field before getting automatically deleted. + + Basically, SetShotAutoDeleteClip for enemies. + + --------------------------------> Shot Functions <-------------------------------- + + CreateShotA2 (overload) + Arguments: + 1) x + 2) y + 3) speed + 4) angle + 5) acceleration + 6) max speed + 7) angular velocity + 8) (int) shot graphic ID + 9) (int) delay + Returns: + (int) object ID + Description: + Overloaded with 9 arguments. + + CreateShotA2 with an additional argument for angular velocity. + + CreateShotC1 + Arguments: + 1) position x + 2) position y + 3) x speed + 4) y speed + 5) angular offset + 6) (int) shot graphic ID + 7) (int) delay + Returns: + (int) object ID + Description: + Creates a shot object using the C-movement mode and returns its object ID. + + C-movement pattern: + The C-movement pattern is essentially B-movement with a twist. + There is an additional "angle offset" property which acts as a rotation vector for the X and Y speeds. + + To be precise: + realSpeedXY = Rotate2D(speedX, speedY, angleOffset); + + CreateShotC2 + Arguments: + 1) position x + 2) position y + 3) x speed + 4) y speed + 5) x acceleration + 6) y acceleration + 7) x max speed + 8) y max speed + 9) angle offset + 10) angle offset acceleration + 11) (int) shot graphic ID + 12) (int) delay + Returns: + (int) object ID + Description: + Creates a shot object using the C-movement mode and returns its object ID. + + CreateShotOC1 + Arguments: + 1) (int) parent object + 2) x speed + 3) y speed + 4) angular offset + 5) (int) shot graphic ID + 6) (int) delay + Returns: + (int) object ID + Description: + Creates a shot object using the C-movement mode on the position of the parent object and returns its object ID. + + GetAllShotID + Arguments: + 1) (const) type + Returns: + (int[]) shot object IDs + Description: + Returns an array of all shot object IDs of the given type. + + Available types: + TARGET_ALL + TARGET_PLAYER + TARGET_ENEMY + + GetShotDataInfoA1 + Returns: + [varies] + Description: + Addition + Change. + + No longer throws an error if the given shot graphic ID is invalid. + + INFO_EXISTS - Returns whether the given shot graphic ID exists. + INFO_PATH - Returns the image path of the given shot graphic ID. + INFO_IS_FIXED_ANGLE - Returns whether the given shot graphic ID has had fixed_angle enabled. + + SetShotTextureFilter + Arguments: + 1) (const) filter min + 2) (const) filter mag + Description: + Sets the min and mag texture filtering modes for rendering shot objects. + + The default filtering modes are FILTER_LINEAR and FILTER_LINEAR. + + --------------------------------> Item Functions <-------------------------------- + + SetItemAutoDeleteClip + Arguments: + 1) (int) left + 2) (int) top + 3) (int) right + 4) (int) bottom + Description: + Sets the margin that item objects are allowed to traverse past the edges of the STG field before getting automatically deleted. + + Basically, SetShotAutoDeleteClip for items. + + GetItemIdInCircleA1 + Arguments: + 1) circle x + 2) circle y + 3) circle radius + Returns: + (int[]) item object IDs + Description: + Returns the object ID of all item objects within the specified circle. + + GetItemIdInCircleA2 + Arguments: + 1) circle x + 2) circle y + 3) circle radius + 4) (int) item type + Returns: + (int[]) item object IDs + Description: + Returns the object ID of all item objects of the specified type within the specified circle. + + SetItemTextureFilter + Arguments: + 1) (const) filter min + 2) (const) filter mag + Description: + Sets the min and mag texture filtering modes for rendering item objects. + + The default filtering modes are FILTER_LINEAR and FILTER_LINEAR. + + --------------------------------> Intersection Functions <-------------------------------- + + IsIntersected_Obj_Obj + Arguments: + 1) (int) object ID 1 + 2) (int) object ID 2 + Returns: + (bool) intersection + Description: + Returns true if any of both object's hitboxes intersect at least once. + + IsIntersected_Obj_Obj_All + Arguments: + 1) (int) object ID 1 + 2) (int) object ID 2 + Returns: + (bool) intersection + Description: + Returns true if all of both object's hitboxes intersect with any of each other's at least once. + + --------------------------------> Move Object Functions <-------------------------------- + + ObjMove_SetSpeed + Description: + Addition. + + Also works on B-pattern and C-pattern movements. + + ObjMove_SetAngle + Description: + Addition. + + Also works on B-pattern and C-pattern movements. + + ObjMove_SetAcceleration + Description: + Addition. + + Also works on B-pattern and C-pattern movements. + + ObjMove_SetMaxSpeed + Description: + Addition. + + Also works on B-pattern and C-pattern movements. + + ObjMove_SetAngularVelocity + Description: + Addition. + + Also works on C-pattern movement. + + ObjMove_SetAngularAcceleration + Arguments: + 1) (int) object ID + 2) angular acceleration + Description: + Sets the move object's angular acceleration. + + Works on A-pattern and C-pattern movements. + + ObjMove_SetAngularMaxVelocity + Arguments: + 1) (int) object ID + 2) angular max velocity + Description: + Sets the move object's angular max velocity. + + Works on A-pattern and C-pattern movements. + + ObjMove_SetSpeedX + Arguments: + 1) (int) object ID + 2) speed + Description: + Sets the move object's X speed. + + Works on A-pattern, B-pattern, and C-pattern movements. + + ObjMove_SetSpeedY + Arguments: + 1) (int) object ID + 2) speed + Description: + Sets the move object's Y speed. + + Works on A-pattern, B-pattern, and C-pattern movements. + + ObjMove_SetSpeedXY + Arguments: + 1) (int) object ID + 2) x speed + 2) y speed + Description: + Sets the move object's X and Y speeds. + + Works on A-pattern, B-pattern, and C-pattern movements. + + ObjMove_GetSpeedX + Arguments: + 1) (int) object ID + Returns: + (float) x speed + Description: + Gets the move object's X speed. + + ObjMove_GetSpeedY + Arguments: + 1) (int) object ID + Returns: + (float) y speed + Description: + Gets the move object's Y speed. + + ObjMove_SetDestAtFrame (Overload) + Arguments: + 1) (int) object ID + 2) target x + 3) target y + 4) (int) frame + 5) (const) interpolation mode + Description: + Overloaded with 5 arguments. + + Moves the object to the target position in the given frames using the specified interpolation mode. + + Available movement interpolation modes: + LERP_LINEAR: + Linear interpolation. + LERP_SMOOTH: + Smooth interpolation. + LERP_SMOOTHER: + Smoother interpolation. + LERP_ACCELERATE: + Accelerating interpolation. + LERP_DECELERATE: + Decelerating interpolation. + + ObjMove_AddPatternA2 (overload) + Arguments: + 1) (int) object ID + 2) (int) frame + 3) speed + 4) angle + 5) acceleration + 6) max speed + 7) angular velocity + Description: + Overloaded with 7 arguments. + + Additional ability to specify angular velocity. + + ObjMove_AddPatternA3 + Arguments: + 1) (int) object ID + 2) (int) frame + 3) speed + 4) angle + 5) acceleration + 6) max speed + 7) angular velocity + 8) (int) shot graphic ID + Description: + Change. + + Swapped max speed and angular velocity. + + ObjMove_AddPatternA4 + Arguments: + 1) (int) object ID + 2) (int) frame + 3) speed + 4) angle + 5) acceleration + 6) max speed + 7) angular velocity + 8) (int) shot graphic ID + 9) (int) relative object ID + Description: + Change. + + Swapped max speed and angular velocity. + + ObjMove_AddPatternA5 + Arguments: + 1) (int) object ID + 2) (int) frame + 3) speed + 4) angle + 5) acceleration + 6) max speed + 7) angular velocity + 8) angular acceleration + 9) angular max velocity + 10) (int) shot graphic ID + 11) (int) relative object ID + Description: + Self-explanatory. + + ObjMove_AddPatternC1 + Arguments: + 1) (int) object ID + 2) (int) frame + 3) x speed + 4) y speed + 5) angle offset + Description: + Adds a C-movement pattern to the object that will activate after the specified frames after the function call. + + ObjMove_AddPatternC2 + Arguments: + 1) (int) object ID + 2) (int) frame + 3) x speed + 4) y speed + 5) x acceleration + 6) y acceleration + 7) x max speed + 8) y max speed + 10) angle offset + 11) angle offset velocity + Description: + Self-explanatory. + + ObjMove_AddPatternC3 + Arguments: + 1) (int) object ID + 2) (int) frame + 3) x speed + 4) y speed + 5) x acceleration + 6) y acceleration + 7) x max speed + 8) y max speed + 10) angle offset + 11) angle offset velocity + 12) (int) shot graphic ID + Description: + Self-explanatory. + + ObjMove_AddPatternC4 + Arguments: + 1) (int) object ID + 2) (int) frame + 3) x speed + 4) y speed + 5) x acceleration + 6) y acceleration + 7) x max speed + 8) y max speed + 9) angle offset + 10) angle offset velocity + 11) angle offset acceleration + 12) angle offset max speed + 13) (int) shot graphic ID + Description: + Self-explanatory. + + ObjMove_AddPatternD1 + Arguments: + 1) (int) object ID + 2) (int) frame + 3) target x + 4) target y + 5) speed + Description: + An AddPattern version of ObjMove_SetDestAtSpeed. + + ObjMove_AddPatternD2 + Arguments: + 1) (int) object ID + 2) (int) frame + 3) target x + 4) target y + 5) (int) frame duration + Description: + An AddPattern version of ObjMove_SetDestAtFrame. + + ObjMove_AddPatternD2 (overload) + Arguments: + 1) (int) object ID + 2) (int) frame + 3) target x + 4) target y + 5) (int) frame duration + 6) (const) interpolation mode + Description: + Overloaded with 6 arguments. + + An AddPattern version of ObjMove_SetDestAtFrame. + + ObjMove_AddPatternD3 + Arguments: + 1) (int) object ID + 2) (int) frame + 3) target x + 4) target y + 5) weight + 6) max speed + Description: + An AddPattern version of ObjMove_SetDestAtWeight. + + ObjMove_SetProcessMovement + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + Sets whether the object will be allowed to execute movement-related routines. + + *ObjMove_SetX/Y/Position would still alter the object's position. + + ObjMove_GetProcessMovement + Arguments: + 1) (int) object ID + Returns: + (bool) result + Description: + Returns true if the object is allowed to execute movement-related routines. + + ObjMove_GetMovementType + Arguments: + 1) (int) object ID + Returns: + (const) movement type + Description: + Returns the current movement type of the move object. + + Possible return values: + MOVE_NONE ; The object doesn't have an active movement function. (May be caused by ObjMove_CancelMovement.) + MOVE_ANGLE ; A-pattern movement. (Angle) + MOVE_XY ; B-pattern movement. (XY) + MOVE_XY_ANGLE ; C-pattern movement. (XY-Angle) + MOVE_LINE ; D-pattern movement. (Line, ObjMove_SetDestAtXXX) + MOVE_OTHER ; Other movements. + + ObjMove_CancelMovement + Arguments: + 1) (int) object ID + Description: + Cancels the object's current movement routine. + + --------------------------------> Enemy Object Functions <-------------------------------- + + ObjEnemy_GetInfo + Description: + Addition. + + INFO_DAMAGE_PREVIOUS_FRAME: + Returns the amount of damage the enemy received in the previous frame. + + ObjEnemy_SetAutoDelete + Arguments: + 1) (int) object ID + 2) (bool) auto delete + Description: + ObjShot_SetAutoDelete, but for enemy objects. + + See: SetEnemyAutoDeleteClip + + Default value is false. + + ObjEnemy_SetDeleteFrame + Arguments: + 1) (int) object ID + 2) (int) frame + Description: + ObjShot_SetDeleteFrame, but for enemy objects. + + ObjEnemy_AddLifeEx + Arguments: + 1) (int) object ID + 2) life + Description: + Adds life to the enemy object with respect to the enemy object's maximum damage. + + Negative value (damaging) will count towards the maximum damage as if getting hit by a player shot. + Positive value (healing) will reduce the damage count and allow more damage to be dealt in the frame equal to how much the healing was. + + ObjEnemy_SetMaximumDamage + Arguments: + 1) (int) object ID + 2) maximum damage + Description: + Sets the maximum amount of damage that the enemy object can receive through normal means in a single frame. + + Default value is, for all intents and purposes, infinity. + + ObjEnemy_GetIntersectionCircleListToShot + Arguments: + 1) (int) object ID + Returns: + (float[3][]) intersection circles + Description: + Returns an array of arrays of the enemy object's intersection circle to player shot. + e.g. [[x1, y1, radius1], [x2, y2, radius2], ...] + + ObjEnemy_GetIntersectionCircleListToPlayer + Arguments: + 1) (int) object ID + Returns: + (float[3][]) intersection circles + Description: + Returns an array of arrays of the enemy object's intersection circle to player hitbox. + e.g. [[x1, y1, radius1], [x2, y2, radius2], ...] + + ObjEnemy_SetEnableIntersectionPositionFetching + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + If set to false, the following functions will not include the specified enemy object's hitboxes. + GetEnemyIntersectionPosition + GetEnemyIntersectionPositionByIdA1 + GetEnemyIntersectionPositionByIdA2 + GetAllEnemyIntersectionPosition + + --------------------------------> Enemy Boss Scene Object Functions <-------------------------------- + + ObjEnemyBossScene_GetInfo + Description: + Addition. + + INFO_IS_REQUIRE_ALL_DOWN: + Returns if EV_REQUEST_REQUIRE_ALL_DOWN was set to true. + + ObjEnemyBossScene_EndSpell + Arguments: + 1) (int) boss scene object ID + Description: + Marks the current single as being not-a-spell. + + I literally do not know why I added this. + + ObjEnemyBossScene_SetUnloadCache + Arguments: + 1) (int) boss scene object ID + 2) (bool) unload + Description: + If set to true, will unload all added scripts from the script source cache upon boss scene end or object deletion. + + --------------------------------> Shot Object Functions <-------------------------------- + + ObjShot_SetOwnerType + Arguments: + 1) (int) object ID + 2) (const) type + Description: + Sets the shot object's owner type. + Available types are: + OWNER_PLAYER + OWNER_ENEMY + Shots created inside a player script are set to OWNER_PLAYER by default, OWNER_ENEMY otherwise. + + ObjShot_GetIntersectionEnable + Arguments: + 1) (int) object ID + Returns: + (bool) intersection enable + Description: + Returns whether ObjShot_SetIntersectionEnable was set on the shot object. + + ObjShot_SetIntersectionScaleX + Arguments: + 1) (int) object ID + 2) scale + Description: + Sets the shot object's X hitbox scale. + For normal shots, the true scale is the half-point between the X and Y scales. + + ObjShot_SetIntersectionScaleY + Arguments: + 1) (int) object ID + 2) scale + Description: + Sets the shot object's Y hitbox scale. + For normal shots, the true scale is the half-point between the X and Y scales. + + ObjShot_SetIntersectionScaleXY + Arguments: + 1) (int) object ID + 2) X scale + 3) Y scale + Description: + Sets the shot object's X and Y hitbox scales. + For normal shots, the true scale is the half-point between the X and Y scales. + + Note: Sorry folks, no ellipse hitboxes for you. + + ObjShot_SetPositionRounding + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + If set to true, will cause the shot object to only render in non-floating point coordinates. + + See: Official Touhou games + + ObjShot_SetAngleRounding + Arguments: + 1) (int) object ID + 2) snap angle + Description: + Causes the shot render angle to be rounded to the nearest multiple of the given angle. + If the angle is <= 0, angle rounding will be disabled. + + See: PC-98 Touhou games + + ObjShot_SetDelayMotionEnable + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + If set to true, will enable the shot object to move in its delay period. + Only works on regular shots. + Default is false. + + ObjShot_SetDelayGraphic + Arguments: + 1) (int) object ID + 2) (int) image ID + Description: + Sets the image ID of the shot object's delay cloud. + A negative value will reset the delay cloud graphic to default. + + ObjShot_SetDelayScaleParameter + Arguments: + 1) (int) object ID + 2) parameter 1 (Designated "S0") + 3) parameter 2 (Designated "S1") + 4) parameter 3 (Designated "S2") + Description: + Sets the properties of the shot object's delay cloud's scale. + + DELAY_DEFAULT: + scale = min(S0 + delay / S2, S1) + DELAY_LERP: + scale = lerpFunction(S0, S1, delay / S2) + + ObjShot_SetDelayAlphaParameter + Arguments: + 1) (int) object ID + 2) parameter 1 (Designated "A0") + 3) parameter 2 (Designated "A1") + 4) parameter 3 (Designated "A2") + Description: + Sets the properties of the shot object's delay cloud's alpha. + Alpha value range is 0 to 1. + + DELAY_DEFAULT: + alpha = min(A0 + delay / A2, A1) + DELAY_LERP: + alpha = lerpFunction(A0, A1, delay / A2) + + ObjShot_SetDelayMode + Arguments: + 1) (int) object ID + 2) (const) delay mode + 3) (const) scale interpolation mode + 4) (const) alpha interpolation mode + Description: + Sets the properties of the shot object's delay cloud. + + Available delay modes: + DELAY_DEFAULT: + Default Danmakufu delay. + DELAY_LERP: + ZUN-like delay. + Available delay interpolation modes: + LERP_LINEAR: + Linear interpolation. + LERP_SMOOTH: + Smooth interpolation. + LERP_SMOOTHER: + Smoother interpolation. + LERP_ACCELERATE: + Accelerating interpolation. + LERP_DECELERATE: + Decelerating interpolation. + + ObjShot_SetDelayColor + Arguments: + 1) (int) object ID + 2) (int) hex color + Description: + Sets the color of the shot object's delay cloud as an ARGB hexadecimal color value. + + Set to 0 to revert to using the shot data's delay color. + + ObjShot_SetDelayColoringEnable + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + When set to true, enables the object color to affect the shot object's delay cloud. + + ObjShot_SetGrazeInvalidFrame + Arguments: + 1) (int) object ID + 2) (int) cooldown frame + Description: + Sets the shot object's graze cooldown frame. + After being grazed, the shot will be put on graze cooldown, wherein it cannot be grazed for the duration. + + For lasers, the default value is 20. + For normal shots, the default value is 2147483647. + + ObjShot_SetGrazeFrame + Arguments: + 1) (int) object ID + 2) (int) frame + Description: + Sets the shot object's graze frame. + + Internally, this value is reset to the graze invalid frame every time a graze is performed. + This value decreases by 1 every frame, and the shot object is eligible for a graze if it is equal to or less than 0. + + ObjShot_IsValidGraze + Arguments: + 1) (int) object ID + Returns: + (bool) graze validity + Description: + Returns whether the shot object is currently able to be grazed. + + ObjShot_SetPenetrateShotEnable + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + If set to false, the shot will not lose penetration upon collision with another enemy shot. + Intended to be used with players shots, in tandem with ObjShot_SetEraseShot. + + Default is true. + + ObjShot_SetEnemyIntersectionInvalidFrame + Arguments: + 1) (int) object ID + 2) (int) cooldown + Description: + Sets the enemy intersection cooldown duration in frames for the shot object. + + Intersection with an enemy will add the enemy to the shot's cooldown list. + The shot will not be able to intersect enemy objects still on hit cooldown. + + Cooldown is maintained by the shot, not the enemy. + Shot A intersecting and putting an enemy on cooldown will not stop Shot B from registering intersection with the same enemy. + + ObjShot_SetFixedAngle + Arguments: + 1) (int) object ID + 2) (bool) fixed angle + Description: + If set to true, the shot will not visually rotate along its movement angle. + + The default value is specified in the graphic's shot data as "fixed_angle", this function allows you to override that value. + + ObjShot_SetSpinAngularVelocity + Arguments: + 1) (int) object ID + 2) spin angular velocity + Description: + Sets the Z angle spin speed of the shot graphic. + + The default spin speed is specified in the graphic's shot data as "angular_velocity", this function allows you to override that value. + + ObjShot_SetDelayAngularVelocity + Arguments: + 1) (int) object ID + 2) delay angular velocity + Description: + Sets the Z angle spin speed of the shot's delay cloud. + + The default delay spin speed is 0. + + --------------------------------> Straight Laser Object Functions <-------------------------------- + + ObjLaser_SetInvalidLength + Description: + Change. + + Both invalid lengths now scale from 0 to 1 rather than 0 to 100. + + ObjStLaser_SetEnd + Arguments: + 1) (int) object ID + 2) (bool) set + Description: + Sets whether a delay cloud will appear at the end of the straight laser object. + + ObjStLaser_SetEndGraphic + Arguments: + 1) (int) object ID + 2) (int) graphic ID + Description: + Sets the shot image ID of the straight laser object "end" delay cloud. + + See: ObjShot_SetDelayGraphic + + ObjStLaser_SetDelayScale + Arguments: + 1) (int) object ID + 2) source scale multiplier + 3) end scale multiplier + Description: + Sets the scale multipliers of the straight laser object's delay clouds. + The default values are (1, 1). + + ObjStLaser_SetPermitExpand + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + Sets whether the straight laser will expand after the delay period. + Intended for use in delay lines. + + ObjStLaser_GetPermitExpand + Arguments: + 1) (int) object ID + Returns: + (bool) permit expand + Description: + Returns whether the straight laser is permitted to expand after the delay period. + + --------------------------------> Curvy Laser Object Functions <-------------------------------- + + ObjCrLaser_SetTipCapping + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + Sets whether the curvy laser will attempt to keep its graphic's tips proportional to the upper and lower halves of its sprite. + + The exact middle of the sprite will be stretched along the laser's body between the tips. + Can be used to emulate PC-98-styled "cheeto lasers". + + ObjCrLaser_GetNodePointer + Arguments: + 1) (int) object ID + 2) (int) node index + Returns: + (pointer) node pointer + Description: + Returns the pointer value of the specified node index. + The pointer is used in other node-related functions. + + As node traversal is relatively expensive, it is not recommended to repeatedly use this function. + + At each frame, the node at the laser's end is invalidated if the laser is able to move. + Using an invalid pointer may cause a memory access violation. + + ObjCrLaser_GetNodePointerList + Arguments: + 1) (int) object ID + Returns: + (pointer[]) node pointers + Description: + Returns a list of node pointers of the curvy laser object. + The pointers are used in other node-related functions. + + At each frame, the node at the laser's end is invalidated if the laser is able to move. + Using an invalid pointer may cause a memory access violation. + + ObjCrLaser_GetNodePosition + Arguments: + 1) (int) object ID + 2) (pointer) node pointer + Returns: + (float[2]) node position + Description: + Returns the [x, y] position array of the specified node. + + The node pointer is obtained with ObjCrLaser_GetNodePointer[List], do NOT pass in any other values. + + ObjCrLaser_GetNodeAngle + Arguments: + 1) (int) object ID + 2) (pointer) node pointer + Returns: + (float) node angle + Description: + Returns the facing angle of the specified node. + + The node pointer is obtained with ObjCrLaser_GetNodePointer[List], do NOT pass in any other values. + + ObjCrLaser_GetNodeWidthScale + Arguments: + 1) (int) object ID + 2) (pointer) node pointer + Returns: + (float) node width + Description: + Returns the render width scale of the specified node. + + The node pointer is obtained with ObjCrLaser_GetNodePointer[List], do NOT pass in any other values. + + ObjCrLaser_GetNodeColor + Arguments: + 1) (int) object ID + 2) (pointer) node pointer + Returns: + (int[4]) node color + Description: + Returns the [a, r, g, b] color array of the specified node. + + The node pointer is obtained with ObjCrLaser_GetNodePointer[List], do NOT pass in any other values. + + ObjCrLaser_GetNodeColorHex + Arguments: + 1) (int) object ID + 2) (pointer) node pointer + Returns: + (int) hex color + Description: + Returns the ARGB hexadecimal color value of the specified node. + + The node pointer is obtained with ObjCrLaser_GetNodePointer[List], do NOT pass in any other values. + + ObjCrLaser_SetNode + Arguments: + 1) (int) object ID + 2) (pointer) node pointer + 3) node X + 4) node Y + 5) node angle + 6) (int) node hex color + Description: + Sets the position, angle, and color of the specified node. + + The node pointer is obtained with ObjCrLaser_GetNodePointer[List], do NOT pass in any other values. + + ObjCrLaser_SetNode (Overload) + Arguments: + 1) (int) object ID + 2) (pointer) node pointer + 3) node X + 4) node Y + 5) node angle + 6) (int) node hex color + 7) =node width scale + Description: + Overloaded with 7 arguments. + + Additional ability to set node render width render. + + ObjCrLaser_SetNodePosition + Arguments: + 1) (int) object ID + 2) (pointer) node pointer + 3) node X + 4) node Y + Description: + Sets the position of the specified node. + + The node pointer is obtained with ObjCrLaser_GetNodePointer[List], do NOT pass in any other values. + + ObjCrLaser_SetNodeAngle + Arguments: + 1) (int) object ID + 2) (pointer) node pointer + 3) node angle + Description: + Sets the angle of the specified node. + + The node pointer is obtained with ObjCrLaser_GetNodePointer[List], do NOT pass in any other values. + + ObjCrLaser_SetNodeWidthScale + Arguments: + 1) (int) object ID + 2) (pointer) node pointer + 3) node scale + Description: + Sets the render width scale of the specified node. + + The node pointer is obtained with ObjCrLaser_GetNodePointer[List], do NOT pass in any other values. + + ObjCrLaser_SetNodeColor + Arguments: + 1) (int) object ID + 2) (pointer) node pointer + 3) (int) node hex color + Description: + Sets the color of the specified node as an ARGB hexadecimal color value. + + The node pointer is obtained with ObjCrLaser_GetNodePointer[List], do NOT pass in any other values. + + ObjCrLaser_AddNode + Arguments: + 1) (int) object ID + 2) node X + 3) node Y + 4) node angle + 5) (int) node hex color + Description: + Adds a laser node at the end of the curvy laser with the specified position, angle, and color. + + ObjCrLaser_AddNode (Overload) + Arguments: + 1) (int) object ID + 2) node X + 3) node Y + 4) node angle + 5) (int) node hex color + 6) node width scale + Description: + Overloaded with 6 arguments. + + Additional ability to specify node render width render. + + --------------------------------> Shot Pattern Object Functions <-------------------------------- + + ObjPatternShot_Create + Description: + Creates a pattern shot object and returns its object ID. + + Can be used for firing a large amount of bullets with only a few function calls, like in ZUN's ECL scripts. + + ObjPatternShot_Fire + Arguments: + 1) (int) object ID + Description: + Fires the shot pattern defined by the given shot pattern object. + + ObjPatternShot_FireReturn + Arguments: + 1) (int) object ID + Returns: + (int[]) shot IDs + Description: + Fires the shot pattern defined by the given shot pattern object and returns the IDs of the created shots in an array. + + ObjPatternShot_SetParentObject + Arguments: + 1) (int) object ID + 2) (int) parent object ID + Description: + Sets the parent object of the given shot pattern object. + + ObjPatternShot_SetPatternType + Arguments: + 1) (int) object ID + 2) (const) type + Description: + Sets the firing pattern of the given shot pattern object. + Available pattern types: + PATTERN_FAN + PATTERN_FAN_AIMED + PATTERN_RING + PATTERN_RING_AIMED + PATTERN_ARROW + PATTERN_ARROW_AIMED + PATTERN_POLYGON + - [way]: Number of polygon vertices. + - [stack]: Number of shots per sides. + - [angle argument]: Edge skip, should normally be 1. Other values will result in polygrams. + - [speed argument]: No effect. + PATTERN_POLYGON_AIMED + PATTERN_ELLIPSE + - [stack]: No effect. + - [angle argument]: Angle of the ellipse. (Not of the shots) + - [base speed]: Max speed at the ends of the primary axis. + - [speed argument]: Max speed at the ends of the secondary axis. + PATTERN_ELLIPSE_AIMED + PATTERN_SCATTER_ANGLE + PATTERN_SCATTER_SPEED + PATTERN_SCATTER + PATTERN_LINE + PATTERN_ROSE + - [way]: Number of "petals". + - [stack]: Number of shots per petals. + + ObjPatternShot_SetShotType + Arguments: + 1) (int) object ID + 2) (const) type + Description: + Sets the shot type of the given shot pattern object. + Supported types: + OBJ_SHOT + OBJ_LOOSE_LASER + OBJ_CURVE_LASER + + ObjPatternShot_SetInitialBlendMode + Arguments: + 1) (int) object ID + 2) (const) blend type + Description: + Sets the initial blend type of the shots. + See ObjRender_SetBlendType for the list of blend types. + + ObjPatternShot_SetShotCount + Arguments: + 1) (int) object ID + 2) (int) way + 3) (int) stack + Description: + Sets the shot way and shot stack of the given shot pattern object. + + ObjPatternShot_SetSpeed + Arguments: + 1) (int) object ID + 2) base speed + 3) speed argument + Description: + Sets the shot speed and argument of the given shot pattern object. + + ObjPatternShot_SetAngle + Arguments: + 1) (int) object ID + 2) base angle + 3) angle argument + Description: + Sets the shot angle and argument of the given shot pattern object. + + ObjPatternShot_SetBasePoint + Arguments: + 1) (int) object ID + 2) X position + 3) Y position + Description: + Sets the base firing position of the given shot pattern object. + Defaults to the parent object's position if not used. + + Use PATTERN_BASEPOINT_RESET in either arguments to reset it to the parent object's position. + + ObjPatternShot_SetBasePointOffset + Arguments: + 1) (int) object ID + 2) X offset + 3) Y offset + Description: + Sets the firing position offset of the given shot pattern object from its base point. + + ObjPatternShot_SetBasePointOffsetCircle + Arguments: + 1) (int) object ID + 2) angle + 3) radius + Description: + Sets the firing position offset in a circular manner of the given shot pattern object from its base point. + + Equivalent to ObjPatternShot_SetBasePointOffset(obj, radius * cos(angle), radius * sin(angle)); + + ObjPatternShot_SetShootRadius + Arguments: + 1) (int) object ID + 2) radius + Description: + Causes the shots to be fired a certain radius away from their base points. + + ObjPatternShot_SetDelay + Arguments: + 1) (int) object ID + 2) (int) delay + Description: + Sets the shot delay of the given shot pattern object. + + ObjPatternShot_SetGraphic + Arguments: + 1) (int) object ID + 2) (int) graphic + Description: + Sets the shot image ID of the given shot pattern object. + + ObjPatternShot_SetLaserParameter + Arguments: + 1) (int) object ID + 2) width + 3) length + Description: + Sets the length and width of the given shot pattern object. + Has no effect if the pattern is firing normal shots. + + ObjPatternShot_CopySettings + Arguments: + 1) (int) destination object ID + 2) (int) source object ID + Description: + Copies the settings of a shot pattern object to another. + + ObjPatternShot_AddTransform + Arguments: + 1) (int) object ID + 2) (const) transform type + 3+) transform arguments... + Description: + Adds a transformation to the shot pattern object. + + Transforms arguments will be designated, in order: [arg0], [arg1], [arg2], etc... + + Available transformations are: + TRANSFORM_WAIT (argc = 1) + - Delays the next transformation for [arg0] frames. + TRANSFORM_ADD_SPEED_ANGLE (argc = 4) + - Waits for [arg1] frames. (Does not delay the next transformation) + - For [arg0] frames, sets acceleration to [arg2]. + - For [arg0] frames, sets angular velocity to [arg3]. + TRANSFORM_ANGULAR_MOVE (argc = 3) + - For [arg0] frames, sets angular velocity to [arg1]. + - Sets shot graphic "spin" to [arg2]. + TRANSFORM_N_DECEL_CHANGE (argc = 5) + - For [arg1] times, decelerates/accelerates the shot to a complete halt in [arg0] frames. (See: Aunn's first spell) + - Movement will then change depending on [arg2]. + - 0: Changes the movement angle to [arg4]. + - 1: Increments the movement angle by [arg4]. + - 2: Aims to the player with an added randomness factor of -[arg4] to [arg4]. + - 3: Aims to the player with an increment of [arg4]. + - 4: Angle becomes random. + - 5, other: No angle change. + - All modes sets the speed to [arg3]. + - Delay the next transformation by ([arg0] * [arg1]) frames. + TRANSFORM_GRAPHIC_CHANGE (argc = 1) + - Changes the shot graphic to [arg0]. + TRANSFORM_BLEND_CHANGE (argc = 1) + - Changes the shot blend type to [arg0]. + TRANSFORM_TO_SPEED_ANGLE (argc = 3) + - Gradually changes the shot's speed to [arg1] in [arg0] frames. + - Gradually changes the shot's angle to [arg2] in [arg0] frames. + - Using TOPLAYER_CHANGE will aim the shot to the player object. + - NO_CHANGE can be used for [arg1] and [arg2]. + TRANSFORM_ADDPATTERN_A1 (argc = 3) + - Applies [ObjMove_AddPatternA1(obj, [arg0], [arg1], [arg2])] + TRANSFORM_ADDPATTERN_A2 (argc = 8) + - Applies [ObjMove_AddPatternA4(obj, [arg0], [arg1], [arg2], [arg3], [arg4], [arg5], [arg6], [arg7])] + TRANSFORM_ADDPATTERN_B1 (argc = 3) + - Applies [ObjMove_AddPatternB1(obj, [arg0], [arg1], [arg2])] + TRANSFORM_ADDPATTERN_B2 (argc = 8) + - Applies [ObjMove_AddPatternB3(obj, [arg0], [arg1], [arg2], [arg3], [arg4], [arg5], [arg6], [arg7])] + TRANSFORM_ADDPATTERN_C1 (argc = 3) + - Applies [ObjMove_AddPatternC1(obj, [arg0], [arg1], [arg2])] + TRANSFORM_ADDPATTERN_C2 (argc = 10) + - Applies [ObjMove_AddPatternC3(obj, [arg0], [arg1], [arg2], [arg3], [arg4], [arg5], [arg6], [arg7], [arg8], [arg9])] + + ObjPatternShot_SetTransform + Arguments: + 1) (int) object ID + 2) (int) transform index + 3) (const) transform type + 4+) transform arguments... + Description: + Sets transformation to the specified transform index. + + --------------------------------> Collision Object Functions <-------------------------------- + + ObjCol_GetListOfIntersectedShotID + Arguments: + 1) (int) object ID + 2) (const) shot owner type + Returns: + (int[]) intersected shot IDs + Description: + Returns an array of all shot objects of the specified owner type currently intersecting with the object. + + Available owner types are: + OWNER_PLAYER + OWNER_ENEMY + + --------------------------------> Item Object Functions <-------------------------------- + + ObjItem_SetAutoCollectEnableFlags + Arguments: + 1) (int) object ID + 2) (int) flags + Description: + Sets the autocollection enable flags of the item object. + Autocollection enable flags dictate which autocollection types will affect the item object. + + Available flags: + ITEM_AUTOCOLLECT_PLAYER_SCOPE + ITEM_AUTOCOLLECT_COLLECT_ALL + ITEM_AUTOCOLLECT_POC_LINE + ITEM_AUTOCOLLECT_COLLECT_CIRCLE + ITEM_AUTOCOLLECT_ALL + + Flags can be combined with bitwise OR. + Using 0 will cause the item object to be impervious to all autocollection types. + + ObjItem_GetInfo + Arguments: + 1) (int) object ID + 2) (const) info type + Returns: + [varies] + Description: + Addition. + + INFO_ITEM_MOVE_TYPE: + Returns the move type of the item object. + Returned values are the possible inputs of ObjItem_SetDefinedMovePatternA1. + + INFO_ITEM_TYPE: + Returns the graphic ID of the item object. + + ObjItem_SetMoveToPlayer + Arguments: + 1) (int) object ID + 2) (bool) move to player + Description: + Causes the item object to start or stop moving to the player. + + If set to true, EV_COLLECT_ITEM will be notified. + If set to false, EV_CANCEL_ITEM will be notified. + + ObjItem_IsMoveToPlayer + Arguments: + 1) (int) object ID + Returns: + (bool) result + Description: + Returns whether the item object is moving to the player. + + ObjItem_Collect + Arguments: + 1) (int) object ID + Description: + Causes the item object to be instantly collected. + + Not affected by ObjItem_SetIntersectionEnable. + + ObjItem_SetAutoDelete + Arguments: + 1) (int) object ID + 2) (bool) auto delete + Description: + Sets whether the item will be subject to the auto-deletion clip. + + The auto-deletion clip size can be altered using SetItemAutoDeleteClip. + + ObjItem_SetIntersectionRadius + Arguments: + 1) (int) object ID + 2) (int) radius + Description: + Sets the item object's player intersection radius. + + ObjItem_SetIntersectionEnable + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + Sets whether the item object is allowed to directly intersect with the player. + + ObjItem_GetIntersectionEnable + Arguments: + 1) (int) object ID + Returns: + (bool) enable + Description: + Returns whether the item object has intersection enabled. + + ObjItem_SetDefaultCollectMovement + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + Sets whether the item object will use the built-in autocollection behaviour. + + Intended to be used in tandem with EV_COLLECT_ITEM. + + ObjItem_SetPositionRounding + Arguments: + 1) (int) object ID + 2) (bool) enable + Description: + If set to true, will cause the item object to only render in non-floating point coordinates. + +----------------------------------------------> [Item Script] <---------------------------------------------- + + --------------------------------> Events <-------------------------------- + + EV_DELETE_SHOT_TO_ITEM is notified when an item is deleted and turned into an item. + Actions that trigger this event: + - Using ObjShot_ToItem. + - Using DeleteShotAll or DeleteShotInCircle with TYPE_ITEM. + + Event arguments: + 1) (int) shot object ID + 2) (float[]) position [x, y] + 3) (bool) collided with player + If true, the shot was deleted from coliision with a player hitbox. + 4) (int) shot image ID + + EV_COLLECT_ITEM is notified when an item is autocollected. + Actions that trigger this event: + - Collision with the player's item scope. + - The player moving up into the item autocollection line. + - Using CollectItemsInCircle, CollectAllItems, or ObjItem_SetMoveToPlayer. + + Event arguments: + 1) (int) item object ID + 2) (int) item type + 3) (int) collection type + 0 - Player scope + 1 - Player autocollection line + 2 - Via CollectItemsInCircle + 3 - Via CollectAllItems + 4 - Via ObjItem_SetMoveToPlayer + 4) (float) collection info + Varies with collection type: + Type 0 -> Player item scope radius + Type 1 -> Player autocollection line position + Type 2 -> Collection circle size + Type 3 -> 0 + Type 4 -> 0 + + EV_CANCEL_ITEM is notified when an item's autocollection is canceled. + Actions that trigger this event: + - The player leaving STATE_NORMAL while the item is in the middle of being collected. + - Using CancelCollectItems or ObjItem_SetMoveToPlayer. + + Event arguments: + 1) (int) item object ID + 2) (int) item type + 3) (int) cancel type + 0 - Player died + 1 - Via CancelCollectItems + 2 - Via ObjItem_SetMoveToPlayer + +----------------------------------------------> [Player Script] <---------------------------------------------- + + --------------------------------> Normal Functions <-------------------------------- + + KillPlayer + Description: + Kills the player. + + --------------------------------> Shot Functions <-------------------------------- + + CreatePlayerShotA1 + Description: + Change. + No longer returns a null value if SetForbidPlayerShot was set to true. + + --------------------------------> Events <-------------------------------- + + EV_DELETE_SHOT_PLAYER is notified to the player script when a player shot is deleted upon collision with an enemy intersection. + ObjShot_SetPenetration(obj, 0) can also be used to manually activate the event. + + Event arguments: + 1) (int) shot object ID + 2) (float[2]) position + 3) (int) shot graphic ID + 4) (int) object ID that the shot collided with + - Will be ID_INVALID in case of manual activation. \ No newline at end of file diff --git a/docs/New Scripting Features.txt b/docs/New Scripting Features.txt new file mode 100644 index 0000000..f7ebe66 --- /dev/null +++ b/docs/New Scripting Features.txt @@ -0,0 +1,716 @@ +- Re: Syntax Tutorial + + - Number literals + + - Base literals + + WriteLog(0b1011); //Binary literal, outputs 11 + WriteLog(0o503); //Octal literal, outputs 323 + WriteLog(0x8f62); //Hexadecimal literal, outputs 36706 + + Base literals default to integer type unless suffixed otherwise. + + - Suffix + + - "f" / "F" + Forces a number literal to a float type. + - "i" / "I" + Forces a number literal to an integer type. + + Example: + WriteLog(5); //5.000000 + WriteLog(5f); //5.000000 + WriteLog(5i); //5 + WriteLog(0x5f); //95 + WriteLog(0x5fi); //95 + WriteLog(7.76); //7.760000 + WriteLog(7.76f); //7.760000 + WriteLog(7.76i); //7 + + - Digit separator + + The "_" character can be used in number literals to aid in visibility. + Has no effect on the resultant value. + + WriteLog(5000000000i); //5000000000 + WriteLog(5_000_000_000i); //still 5000000000 + WriteLog(0x7f23a7e2); //2133043170 + WriteLog(0x7f23_a7e2); //still 2133043170 + + - Variables + + - Explicit types + + Originally, you'd declare a variable with one of these three keywords: + - let + - var + - real + All three keywords had the same effect on the declaration. + + However, with version 1.30a, the scripting language has gone through a considerable amount of changes as follows: + - "real" has been renamed to "float". (1.32a) + + - You may now explicitly state the type of the variable you are declaring. + + Example: + int a = 700; //typeof(a) == VAR_INT + float b = 56.243; //typeof(b) == VAR_FLOAT + char c = '0'; //typeof(c) == VAR_CHAR + bool d = false; //typeof(d) == VAR_BOOL + string e = "aubergine"; //typeof(e) == VAR_STRING + int[] f = [4i, 8]; //typeof(f) == VAR_ARRAY, ftypeof(f) == VAR_INT + + - This does not change "let" and "var", they will still behave similarly to "auto" in C++. + + Example: + let a = 700i; //typeof(a) == VAR_INT + let b = 56.243; //typeof(b) == VAR_FLOAT + let c = '0'; //typeof(c) == VAR_CHAR + let d = false; //typeof(d) == VAR_BOOL + let e = "aubergine"; //typeof(e) == VAR_STRING + let f = [4i, 8]; //typeof(f) == VAR_ARRAY, ftypeof(f) == VAR_INT + + - You may not use "let[]" or "const[]". + + An array type declaration may only be used with a non-auto type. + + - Multiple variables declaration. + + Example: + int a, b = 7, c = 100, d; //All will be of type "int" + const bool e = true, f = true; //All will be of type "const bool" + let g = 56, h = true, i = 6i; //g will be "float", h will be "bool", and i will be "int" + bool[][][] j, k; //All will be of type "bool[][][]" (3D bool array) + + - Using "const" + + "const" is used to declare constant variables. + + A standalone "const" will behave like a "let". + "const" can be prefixed or suffixed by another type. + + Constant variables cannot be modified. + Attempting to do so will throw a compile-time error. + + Example: + const a = 1; + const let b = true; + const string c = "xolotl"; + const int d; + + a = 6; //ERROR + d = 10; //ERROR + + - Supplement for smart people + + ph3sx script type | internal C type | size in bytes | + ---------------------------------------------------------- + int | int64_t | 8 | + float | double | 8 | + bool | bool | 1 | + char | wchar_t | 2 | + + - Scoping + + - "local" has been deprecated. While they have not yet been completely removed, it is advisable to stop using it. + + - But what can I use in its place? + + Nothing. + Literally. + + What used to be: + + local { + //... + } + + can now be reduced to just: + + { + //... + } + + Scoping rules will still apply normally, like so: + + let a; + + //Only a is accessible here + + { + let b; + + //a and b are both accessible here + + { + let c; + + //a, b, and c are all accessible here + } + } + + - Operators + + All available script operators are listed as follows. + They are arranged in order of precedence, highest-to-lowest. + + 1. () + Function call + let c = SomeFunc(a, b); + 1. as_x() + Type cast + let a = as_int(x); + let b = as_bool(56); + 1. length() + Array length + let a = length(x); + let b = length([1, 2, 3]); + 1. [] + Array indexing + let a = arr[3]; + let b = [10, 100, 1000][x]; + 1. (| |) + Absolute + let a = (|-4|); //a == 4 + let b = (|a|); //b == 4 + 1. () + Parentheses + 2. ^ + Power (Right-associative) + let a = 2 ^ 4; //a == 16 + let b = 2 ^ 2 ^ 3; //b == 256 + 2. [..] + Array slice + let x = [9, 10, 11, 12, 13]; + let a = x[0..2]; //a == [9, 10] + let b = x[2..999]; //b == [11, 12, 13] + let c = x[3..0]; //c == [11, 10, 9] + 3. + + Unary plus + let a = +6; + 3. - + Unary minus + let a = -10; + 3. ! + Unary logical not + let a = !b; + 3. ~ + Unary bitwise not + let a = ~312; //a == -313 + let b = ~(0b1011001); //b == -90 + 4. * + Multiply + let a = 4 * 10; //a == 40 + 4. / + Divide + let a = 10 / 3; //a == 3.333333 + 4. ~/ + Floored divide + let a = 10 ~/ 3; //a == 3 + 4. % + Remainder (Modulo) + let a = 7 % 4; //a == 3 + 5. + + Add + let a = 3 + 32; //a == 35 + 5. - + Subtract + let a = 9 - 12; //a == -3 + 5. ~ + Array concatenate + let a = [8, 3] ~ [10]; //a == [8, 3, 10] + 6. << + Bitwise shift left + let a = 7 << 3; //a == 56 + 6. >> + Bitwise shift right + let a = 198 >> 2; //a == 49 + 7. == + != + < + <= + > + >= + Comparison + let a = 5 < 6; + let b = a != false; + let c = 10 >= 10; + 8. ^^ + Bitwise XOR + let a = 63 ^^ 234; //a == 213 + 9. | + Bitwise OR + let a = 63 | 234; //a == 255 + 10. & + Bitwise AND + let a = 63 & 234; //a == 42 + 11. || + Logical OR + let a = true || false; //a == true + 11. && + Logical AND + let a = true || false; //a == false + 12. ?: + Ternary expression + let a = x > y ? 10 : 20; + let b = z == 0 ? x * 10 : y + 4; + let c = k ? (y ? 8 : 0) : p ? 5 : 2 + x; + + - Boolean expressions + + - Short-circuiting + + This feature was present in vanilla ph3 as well, but I have yet to see a tutorial mention it, so here it is. + + Short-circuiting (short-circuit evaluation) is an optimization for boolean expressions. + + Take these statements, for example: + bool c = a && b; + bool z = x || y; + + This !RUN-TIME! optimization will occur when expression (a) evaluates to false, + where the evaluation of expression (b) will be completely skipped over. + Conversely, in the second statement, the evaluation of expression (y) will also be skipped over if + expression (x) evaluates to true. + + Short-circuiting will take place left-to-right, so it is beneficial to format your logical expressions + in a way that more lightweight expressions get evaluated sooner rather than later. + + Example: + if (bCheckHit && GetShotIdInCircleA2(...)) { /*...*/ } + + would benefit more from short-circuit evaluation than + + if (GetShotIdInCircleA2(...) && bCheckHit) { /*...*/ } + + Short-circuiting only applies to logical expressions, not bitwise expressions. + + Example: + bool c = a & b; + bool d = a | b; + + Here, both expressions (a) and (b) will be evaluated regardless of the result of expression (a). + + - Loops + + - Ascent/Descent + + Ascent and descent loops remain unchanged, but you may now assign an explicit type to the counter variable. + + Example: + + ascent (i in 0..3) + WriteLog(i); + + Will result in the following output: + 0.000000 + 1.000000 + 2.000000 + + //----------------------------------------------- + + ascent (i in 0i..3) + WriteLog(i); + + Will result in the following output: + 0 + 1 + 2 + + //----------------------------------------------- + + ascent (int i in 0..3) + WriteLog(i); + + Will result in the following output: + 0 + 1 + 2 + + - In ph3sx, two new loops are available for use. + + - For loop + + The for loop is the more generalized version of ascent/descent loops. + + It's also the standard loop format in most programming languages, + which means I don't have to explain its usage here. + + - For-each loop + + The for-each loop is a quick and efficient method to iterate through arrays. + + Example: + + int[] arr = [10, 9, 8, 7]; + for each (int i in arr) + WriteLog(i); + + Will result in the following output: + 10 + 9 + 8 + 7 + + //----------------------------------------------- + + for each (float i in arr) + WriteLog(i); + + Will result in the following output: + 10.000000 + 9.000000 + 8.000000 + 7.000000 + + - The "ref" keyword + + Normally, the array fed into a for-each loop will be a copy of the original array. + However, you can force the loop to directly read from the original array with the "ref" keyword. + + As the array won't be copied, there would also be some performance benefits to be had, + and the loop will respond to any modifications to the array rather than being unaffected. + + Example: + + int[] arr = [1, 2, 3, 4]; + + for each (i in arr) { + if (i % 2 == 0) + arr ~= [5]; + WriteLog(i); + } + WriteLog(arr); + + Will result in the following output: + 1 + 2 + 3 + 4 + [1, 2, 3, 4, 5, 5] + + //----------------------------------------------- + + for each (i in ref arr) { + if (i % 2 == 0) + arr ~= [5]; + WriteLog(i); + } + WriteLog(arr); + + Will result in the following output: + 1 + 2 + 3 + 4 + 5 + 5 + [1, 2, 3, 4, 5, 5] + + - Special syntaxes + + - There is also another declaration syntax for the for-each loop: + + { + int i = 0; + for each (itr in array) { + //... + i++; + } + } + + //is equivalent to: + + for each (i, itr in array) { + //... + } + + - These formats are also allowed: + + for each ((i, itr) in array) { /*...*/ } + for each ((int i, itr) in array) { /*...*/ } + for each (i, float itr in array) { /*...*/ } + for each ((float i, string itr) in array) { /*...*/ } + + - You may use a colon(:) in place of the keyword "in" + + for each (itr : array) { /*...*/ } + for each ((i, itr) : array) { /*...*/ } + + - In addition, there is a new flow control statement "continue". + + "continue" is used in the same manner as "break", but rather than simply ending the loop, + it will merely skip the current iteration of the loop. + + Example: + + ascent (int i in 0..8) { + if (i % 2 == 0) continue; + WriteLog(i); + } + + Will result in the following output: + 1 + 3 + 5 + 7 + + - Unlike in vanilla ph3, "break" can no longer be used outside a loop. + - Attempting to do so will throw a compile-time error. + - The same applies to "continue". + + - Functions, Tasks, Subs ("Callables") + + - Parameters + + Parameters, like variables, can have explicit types. + + Example: + + function Func(int a, float b, const string[] c) {} + + - Function return type + + - You may explicitly specify a function's return type. + + function Func1(a, b) { + return a + b; + } + + WriteLog(Func1(10, 4.2)); //Output: 14 + WriteLog(Func1(10, "sdfs")); //ERROR: Invalid implicit casting + + - Marking a function with type "void" will forbid it from returning a value. + + function Func1(a, b) { + return; //OK: no return value + } + + function Func2(a, b) { + return a + b; //ERROR: void function can't return a value + } + + - Overloading + + Two callables with the same name, but different argument counts, will be treated as two different, unique callables. + + Example: + + function Func() { + return 0; + } + function Func(a) { + return 100; + } + function Func(a, b, c) { + return a + b + c; + } + + DoStuff(); //Returns 0 + DoStuff("asdf"); //Returns 100 + DoStuff(1, 2, 3); //Returns 6 + + - Variadic argument count (varargs) + + - Some default functions now allow for varargs. + + Example: + + NotifyEventAll(EV_USER, 0); + NotifyEventAll(EV_USER, 0, 1, 2, 3); + NotifyEventAll(EV_USER, 0, 1, 2, 3, 4, 5, 6, 7, 8); + + //All of the above are valid calls to NotifyEventAll. + + - You can pass a maximum of around 357900000 arguments, but please please don't actually do that. + + - Scripters currently cannot define their own callables with varargs. + + - Async + + Async blocks can be placed anywhere in the code, they behave like inlined tasks. + + Example: + + function Func() { + WriteLog(0); + + async { + WriteLog(1); + wait(10); + WriteLog(2); + } + + return true; + } + + //is equivalent to: + + function Func() { + WriteLog(0); + + task AsyncTask() { + WriteLog(1); + wait(10); + WriteLog(2); + } + AsyncTask(); + + return true; + } + + - Script + + - Char + + - Backslash escapes (\\) is properly recognized in char/string literals. + - Hexadecimal char literals (\x[hex]) can be used in char/string literals. + Example: + "\x74" -> "t" + '\x3042' -> 'あ' + "\x042\x5f" -> "B_" + + - One-lined statements + + Example: + + ascent (i in 0..10) WriteLog(i); + + if (true) a += 10; + else a -= 4; + + Can be used everywhere except in function/task/sub declarations, async blocks, @-blocks, and local{} blocks. + + - Optimizations + + - The script compiler will try to perform basic optimizations on maths expressions. + + Examples: + + a = 5 + 5 - 1; -> optimize -> a = 9; + a = 5 * 8 / 7; -> optimize -> a = 5.714286; + a = func(b) + 5 % 10; -> optimize -> a = func(b) + 5; + + - Empty loops and blocks will be optimized away during script compiling. + + Examples: + + while (true) {} + + for (let i = 0; i < 10; i++) {} + + ascent (i in 0..100000000) {} + + { + } + + loop (1000) { + } + + for each (i in "aaaaaaaaaa") {} + + async {} + + //All of the above examples will be optimized away + + - Loops containing a single yield will be automatically transformed into a wait. + + Examples: + + loop (60) yield; -> optimize -> wait(60); + + loop (a * 2 + 60 - 20) { -> optimize -> wait(a * 2 + 60 - 20); + yield; + } + +- Text Object Tags + + Text object tags are special formatting patterns that can be used to dynamically alter rendering of text objects. + + Available tags: + + - r + + Inserts a new line. Also resets formatting from other tags. + + - font / f + + Modifies the font. + + Available tag properties: + + - reset / rs / r / clear / clr / c + + Resets the text to its original settings. Present in vanilla ph3 as "clear". + + - size / sz + + Changes the font size. Unchanged from vanilla ph3. + + - ox / oy + + Changes the position offset. + + - it + + Toggles italic. (true/false or 1/0) + + - wg + + Changes the font's weight. + + - br / bg / bb + + Changes the font's bottom color. + + - tr / tg / tb + + Changes the font's top color. + + - or / og / ob + + Changes the font's border color. + + - bc + + Changes the font's bottom color as a (r, g, b) list. + + - tc + + Changes the font's top color as a (r, g, b) list. + + - oc + + Changes the font's border color as a (r, g, b) list. + + Example: + + ObjText_SetText(obj, "Lorem ipsum [font size=48 it=1 bc=(255, 0, 0)]dolor sit[font clr] amet"); + + - ruby + + Creates a ruby(furigana) text. + + Available tag properties: + + - rb + + Sets the main(bottom) text. Unchanged from vanilla ph3. + - rt + + Sets the furigana(top) text. Unchanged from vanilla ph3. + - sz + + Changes the furigana text's font size. + + - wg + + Changes the furigana text's font weight. + + - ox + + Changes the furigana text's left margin. + + - op + + Changes the furigana text's side pitch. \ No newline at end of file diff --git a/game_resource/Advertisement_Gunner.png b/game_resource/Advertisement_Gunner.png new file mode 100644 index 0000000..a3a87cd Binary files /dev/null and b/game_resource/Advertisement_Gunner.png differ diff --git a/game_resource/banner_sketch.png b/game_resource/banner_sketch.png new file mode 100644 index 0000000..4fb0238 Binary files /dev/null and b/game_resource/banner_sketch.png differ diff --git a/game_resource/game_image.png b/game_resource/game_image.png new file mode 100644 index 0000000..b40fce0 Binary files /dev/null and b/game_resource/game_image.png differ diff --git a/game_resource/mushihimesama.png b/game_resource/mushihimesama.png new file mode 100644 index 0000000..4422a12 Binary files /dev/null and b/game_resource/mushihimesama.png differ diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..db895bb Binary files /dev/null and b/license.txt differ diff --git a/readme.txt b/readme.txt new file mode 100644 index 0000000..0f2c13f --- /dev/null +++ b/readme.txt @@ -0,0 +1,52 @@ +● Before We Get Started + This software is a freeware. + The creators are not liable for any mental, physical, or emotional damages caused by using the application. + +● Installation +  1. Use a software that is able to extract .zip files. + If you're seeing this you've probably already done this step. Good job. + 2. Select the path to which to extract the files. + 3. Yeah. + 4. Suffer or enjoy, I don't know. + +● Notes + ■ Running on Wine + If the engine shows an error regarding shader compilation on startup, it's likely because of Wine failing to load required dlls. + + Steps: + 1a) Install winetricks if you haven't yet. + 2a) Run 'winetricks d3dx9 d3dcompiler_43' at the console. + + 1b) If you've performed the above steps, and the engine still does not work, continue below. + 2b) Run winetricks -> "Select the default wineprefix" -> "Run winecfg" + 3b) Select either "Default Settings", or "Add application..." and select the ph3sx binary. + - For "Windows Version", select at least Windows 7. + 4b) Go to the "Libraries" tab, and add overrides for the following dlls: + - d3dx9_43 + - d3dcompiler_43 + 5b) Apply the settings, and everything should now work. + +● Uninstallation +  Simple delete all the related files. + This application does not utilize registry keys nor AppData storage. + +● Key Controls (default) + Arrow Keys: Move + Z: Shoot, Select + X: Bomb, Cancel + Left Shift: Hold for Focused Movement + Left Ctrl: Hold for Fast Mode + R: Return to Script Select Screen (Unavailable by default in package scripts) + Backspace: Restart Script (Unavailable by default in package scripts) + + ** Default key controls are purely engine-default, and may be overridden and changed from script to script. + +Check out the sample scripts for demonstrations of new functions and features. + + + +REPORT BUGS AND/OR GIVE FEATURE REQUESTS TO: + + ● https://github.com/Natashi/Touhou-Danmakufu-ph3sx-2/issues on GitHub + + ● https://discord.gg/f9KFujKGEx on the ph3sx development Discord server \ No newline at end of file diff --git a/resource/img/System_ScriptSelect_Background.png b/resource/img/System_ScriptSelect_Background.png new file mode 100644 index 0000000..bff78aa Binary files /dev/null and b/resource/img/System_ScriptSelect_Background.png differ diff --git a/resource/img/System_Stg_Digit.png b/resource/img/System_Stg_Digit.png new file mode 100644 index 0000000..4bb15dc Binary files /dev/null and b/resource/img/System_Stg_Digit.png differ diff --git a/resource/img/System_Stg_Item.png b/resource/img/System_Stg_Item.png new file mode 100644 index 0000000..288e8ed Binary files /dev/null and b/resource/img/System_Stg_Item.png differ diff --git a/resource/img/System_Title_Background.png b/resource/img/System_Title_Background.png new file mode 100644 index 0000000..d9c8f77 Binary files /dev/null and b/resource/img/System_Title_Background.png differ diff --git a/resource/script/System_PluralStage.txt b/resource/script/System_PluralStage.txt new file mode 100644 index 0000000..ecb2e4f --- /dev/null +++ b/resource/script/System_PluralStage.txt @@ -0,0 +1,33 @@ +//ȂłB + +@Initialize +{ + TEnemy(); +} + +@MainLoop +{ + yield; +} + +@Finalize +{ +} + +task TEnemy +{ + let path = GetMainStgScriptPath(); + let idScript = LoadScript(path); + StartScript(idScript); + + while(!IsCloseScript(idScript) && GetPlayerState() != STATE_END) + { + yield; + } + + loop(300){yield;} + + CloseStgScene(); +} + + diff --git a/resource/script/System_SingleStage.txt b/resource/script/System_SingleStage.txt new file mode 100644 index 0000000..6877d61 --- /dev/null +++ b/resource/script/System_SingleStage.txt @@ -0,0 +1,35 @@ +//ȂłB + +@Initialize +{ + TEnemy(); +} + +@MainLoop +{ + yield; +} + +@Finalize +{ +} + +task TEnemy +{ + let path = GetMainStgScriptPath(); + let obj = ObjEnemyBossScene_Create(); + ObjEnemyBossScene_Add(obj, 0, path); + ObjEnemyBossScene_LoadInThread(obj); + ObjEnemyBossScene_Regist(obj); + + while(!Obj_IsDeleted(obj) && GetPlayerState() != STATE_END) + { + yield; + } + + loop(300){yield;} + + CloseStgScene(); +} + + diff --git a/script/ExRumia/DPS.dnh b/script/ExRumia/DPS.dnh new file mode 100644 index 0000000..5f94d6d --- /dev/null +++ b/script/ExRumia/DPS.dnh @@ -0,0 +1,245 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["DPS Test"] +#Text["thank you Daniel WishMakers"] +#System["script/KevinSystem/Kevin_System.txt"] + +//let shotSheet = GetCurrentScriptDirectory() ~ "./../shot/shot.txt"; + +int bossObj; // This is enemy 1 + +int enm2, enm3; // This is enemy 2 and 3 + +let timer = 0; +let timer2 = 0; +let timer3 = 0; +let timer4 = 0; + +//let phase = 0; +let angle = 0; +let angle2 = 0; +let angle3 = 0; +let angle4 = 0; + +let x = 0; +let y = 0; + +let image_angle = 0; +let HP = 10000000; //- (100 * difficulty); + +// This is for the damage showing +let gl_curDPS = 0; +let gl_curDPS2 = 0; +let gl_curDPS3 = 0; + +let gl_TimeSpent = 0; +let gl_TutorialStr = ""; +const let STR_START = "Release SHOT before testing DPS."; +const let STR_GO = "Press and hold SHOT to start testing DPS."; +const let STR_FINISH = "Release SHOT when you are finished testing DPS."; + +//#include "script/BHA5/script/Lib/BHA5_Lib.txt" + +#include "script/KevinSystem/Universal_Lib.txt" // The library to include all libraries :sans: :nail_care: + +@Event{ + alternative(GetEventType()) + case(EV_REQUEST_LIFE){ + SetScriptResult(HP); + } + case(EV_REQUEST_TIMER){ + SetScriptResult(9999); + } + case(EV_REQUEST_SPELL_SCORE){ + SetScriptResult(1000000); + } +} + +@Initialize{ + //Shot sheet + //LoadTexture(shotSheet); + //LoadEnemyShotData(shotSheet); + + SetPlayerLife(20); + + //Boss registration + bossObj = ObjEnemy_Create(OBJ_ENEMY_BOSS); + ObjEnemy_Regist(bossObj); + //SetIntersectionVisualization(true); + + let imgExRumia = GetModuleDirectory() ~ "script/ExRumia/ExRumia.png"; + ObjPrim_SetTexture(bossObj, imgExRumia); + ObjSprite2D_SetSourceRect(bossObj, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(bossObj); + ObjRender_SetScaleXYZ(bossObj, 1.5, 1.5, 1); + ObjRender_SetColor(bossObj, 0xB93C3C); + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, 550, 1); + + enm2 = ObjEnemy_Create(OBJ_ENEMY); + ObjEnemy_Regist(enm2); + //SetIntersectionVisualization(true); + + //let imgExRumia = GetModuleDirectory() ~ "script/ExRumia/ExRumia.png"; + ObjPrim_SetTexture(enm2, imgExRumia); + ObjSprite2D_SetSourceRect(enm2, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(enm2); + ObjRender_SetScaleXYZ(enm2, 1.5, 1.5, 1); + ObjRender_SetColor(enm2, 0xDC5959); + ObjMove_SetDestAtFrame(enm2, STG_WIDTH/2, 300, 1); + + ObjEnemy_SetMaximumDamage(enm2, 2000); + + enm3 = ObjEnemy_Create(OBJ_ENEMY); + ObjEnemy_Regist(enm3); + //SetIntersectionVisualization(true); + + //let imgExRumia = GetModuleDirectory() ~ "script/ExRumia/ExRumia.png"; + ObjPrim_SetTexture(enm3, imgExRumia); + ObjSprite2D_SetSourceRect(enm3, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(enm3); + ObjRender_SetScaleXYZ(enm3, 1.5, 1.5, 1); + ObjRender_SetColor(enm3, 0xFF8383); + ObjMove_SetDestAtFrame(enm3, STG_WIDTH/2, 50, 1); + + ObjEnemy_SetMaximumDamage(enm3, 2000); + + ObjEnemy_SetMaximumDamage(bossObj, 2000); + + main; + display; + TFinalize; +} + +@MainLoop{ + + ObjEnemy_SetIntersectionCircleToShot(bossObj,ObjMove_GetX(bossObj),ObjMove_GetY(bossObj),128); + ObjEnemy_SetIntersectionCircleToShot(enm2,ObjMove_GetX(enm2),ObjMove_GetY(enm2),128); + ObjEnemy_SetIntersectionCircleToShot(enm3,ObjMove_GetX(enm3),ObjMove_GetY(enm3),128); + + //ObjEnemy_SetIntersectionCircleToPlayer(bossObj,ObjMove_GetX(bossObj),ObjMove_GetY(bossObj),32); + + timer++; + timer2++; + x = ObjMove_GetX(bossObj); + y = ObjMove_GetY(bossObj); + ObjRender_SetAngleZ(bossObj,image_angle); + + //main; + yield; +} + +task TFinalize { + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){yield;} + Obj_Delete(bossObj); + DeleteShotAll(TYPE_ALL, TYPE_IMMEDIATE); + SetAutoDeleteObject(true); + CloseScript(GetOwnScriptID()); + return; +} + +task display { + let objText = CreateTextObject(100,300, 24, "Release SHOT to start testing DPS."); + let objMain = CreateTextObject(100,400, 24, "Avg DPS (Front): [r]Frames: "); + let objMain2 = CreateTextObject(100,500, 24, "Avg DPS (Middle): "); + let objMain3 = CreateTextObject(100,600, 24, "Avg DPS (Back): "); + + loop { + ObjText_SetText(objText, gl_TutorialStr); + ObjText_SetText(objMain, StringFormat("Avg DPS (Front): %f[r]Frames: %d", "fd", gl_curDPS, gl_TimeSpent)); + ObjText_SetText(objMain2, StringFormat("Avg DPS (Middle): %f", "f", gl_curDPS2)); + ObjText_SetText(objMain3, StringFormat("Avg DPS (Back): %f", "f", gl_curDPS3)); + yield; + } +} + +// thanks wish + +task main { + let count = 0; + let damage = 0; + let damage2 = 0; + let damage3 = 0; + + loop { + //Reinitialize + count = 0; + damage = 0; + damage2 = 0; + damage3 = 0; + ObjEnemy_SetLife(bossObj, HP); + ObjEnemy_SetLife(enm2, HP); + ObjEnemy_SetLife(enm3, HP); + gl_TutorialStr = STR_START; + + //Wait for shot to not be held. + while(count < 60) { + if (CheckShotRelease) { + count++; + } + else { + count = 0; + } + yield; + } + + //Wait until player starts pressing SHOT. + count = 0; + gl_TutorialStr = STR_GO; + + while(!CheckShotHeld) { + yield; + } + + while(CheckShotHeld) { + count++; + damage += (HP - ObjEnemy_GetInfo(bossObj, INFO_LIFE)); + damage2 += (HP - ObjEnemy_GetInfo(enm2, INFO_LIFE)); + damage3 += (HP - ObjEnemy_GetInfo(enm3, INFO_LIFE)); + ObjEnemy_SetLife(bossObj, HP); + ObjEnemy_SetLife(enm2, HP); + ObjEnemy_SetLife(enm3, HP); + gl_TimeSpent = count; + if (count % 60 == 0) { + gl_curDPS = damage; + gl_curDPS2 = damage2; + gl_curDPS3 = damage3; + gl_TutorialStr = STR_FINISH; + damage = 0; + damage2 = 0; + damage3 = 0; + } + yield; + } + + } +} + +function CheckShotRelease { + return ((GetVirtualKeyState(VK_SHOT) == KEY_PULL) || (GetVirtualKeyState(VK_SHOT) == KEY_FREE)); +} + +function CheckShotHeld { + return ((GetVirtualKeyState(VK_SHOT) == KEY_PUSH) || (GetVirtualKeyState(VK_SHOT) == KEY_HOLD)); +} + +//mkm fxn +function CreateTextObject(let mx, let my, let size, let text) +{ + let obj = ObjText_Create(); + ObjText_SetText(obj, text); + ObjText_SetFontSize(obj, size); + ObjText_SetFontBold(obj, true); + ObjText_SetFontColorTop(obj, 128, 128, 255); + ObjText_SetFontColorBottom(obj, 64, 64, 255); + ObjText_SetFontBorderType(obj, BORDER_FULL); + ObjText_SetFontBorderColor(obj,255, 255, 255); + ObjText_SetFontBorderWidth(obj, 2); + Obj_SetRenderPriorityI(obj, 10); + ObjRender_SetX(obj, mx); + ObjRender_SetY(obj, my); + return obj; +} + + + + diff --git a/script/ExRumia/ExRumia(星符「ミッドナイトレヴァリエ」).jpg b/script/ExRumia/ExRumia(星符「ミッドナイトレヴァリエ」).jpg new file mode 100644 index 0000000..f227107 Binary files /dev/null and b/script/ExRumia/ExRumia(星符「ミッドナイトレヴァリエ」).jpg differ diff --git a/script/ExRumia/ExRumia.png b/script/ExRumia/ExRumia.png new file mode 100644 index 0000000..1a065a8 Binary files /dev/null and b/script/ExRumia/ExRumia.png differ diff --git a/script/ExRumia/ExRumia01.txt b/script/ExRumia/ExRumia01.txt new file mode 100644 index 0000000..31be75d Binary files /dev/null and b/script/ExRumia/ExRumia01.txt differ diff --git a/script/ExRumia/ExRumiaSpell01.txt b/script/ExRumia/ExRumiaSpell01.txt new file mode 100644 index 0000000..ed0cd8a Binary files /dev/null and b/script/ExRumia/ExRumiaSpell01.txt differ diff --git a/script/ExRumia/ExRumia_Package_Main.txt b/script/ExRumia/ExRumia_Package_Main.txt new file mode 100644 index 0000000..7827208 Binary files /dev/null and b/script/ExRumia/ExRumia_Package_Main.txt differ diff --git a/script/ExRumia/ExRumia_Package_ReplaySelectScene.txt b/script/ExRumia/ExRumia_Package_ReplaySelectScene.txt new file mode 100644 index 0000000..721288a Binary files /dev/null and b/script/ExRumia/ExRumia_Package_ReplaySelectScene.txt differ diff --git a/script/ExRumia/ExRumia_Plural.txt b/script/ExRumia/ExRumia_Plural.txt new file mode 100644 index 0000000..4e10328 Binary files /dev/null and b/script/ExRumia/ExRumia_Plural.txt differ diff --git a/script/ExRumia/ExRumia_Stage.txt b/script/ExRumia/ExRumia_Stage.txt new file mode 100644 index 0000000..c63a5f3 Binary files /dev/null and b/script/ExRumia/ExRumia_Stage.txt differ diff --git a/script/ExRumia/Title.png b/script/ExRumia/Title.png new file mode 100644 index 0000000..48fcf53 Binary files /dev/null and b/script/ExRumia/Title.png differ diff --git a/script/GayGunner_Package.dnh b/script/GayGunner_Package.dnh new file mode 100644 index 0000000..89002d6 Binary files /dev/null and b/script/GayGunner_Package.dnh differ diff --git a/script/Gay_Package.dnh b/script/Gay_Package.dnh new file mode 100644 index 0000000..054b4ee Binary files /dev/null and b/script/Gay_Package.dnh differ diff --git a/script/GunnerParade/config.dat b/script/GunnerParade/config.dat new file mode 100644 index 0000000..2aae69b Binary files /dev/null and b/script/GunnerParade/config.dat differ diff --git a/script/Jam10/Game_Plural.dnh b/script/Jam10/Game_Plural.dnh new file mode 100644 index 0000000..7694a18 --- /dev/null +++ b/script/Jam10/Game_Plural.dnh @@ -0,0 +1,208 @@ +#TouhouDanmakufu[Plural] +#ScriptVersion[3] +#Title["Game Plural"] +#Text["pilk"] +#System["script/KevinSystem/Kevin_System.txt"] +//#Player["script/KevinPackage/KevinScript_Players/PankevKouda/KevKou_Main.dnh", "script/KevinPackage/KevinScript_Players/MariHousui/MariHousui_Main.dnh"] + +let csd = GetCurrentScriptDirectory(); + +let obj = ObjEnemyBossScene_Create(); +int objBGM = ObjSound_Create(); +int objBGMBoss = ObjSound_Create(); + +#include "script/KevinSystem/Universal_Lib.txt" +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" +#include "script/Jam10/Stage_Background.dnh" + +int LifeStart = GetCommonData("Starting Lives", 3); + +bool stageStart = false; +bool bossStart = false; +float BGMRate = GetAreaCommonData("Config", "BGMVol", 100) * 0.01; + +let POINTER_CHAIN = LoadAreaCommonDataValuePointer("PIV", "ChainAmount", 1); +let POINTER_CHAINGAUGE = LoadAreaCommonDataValuePointer("PIV", "ChainGauge", 0); +let POINTER_SPECIALAMMO = LoadAreaCommonDataValuePointer("PIV", "SpecialAmmo", 100); +let POINTER_SPECIALCHECK = LoadAreaCommonDataValuePointer("PIV", "IsUsingSpecial", false); +let POINTER_CHAINCHECK = LoadAreaCommonDataValuePointer("PIV", "IsChaining", false); + +string DATA_PLAYER = ""; +string DATA_DIFFICULTY = ""; + +@Event{ + + alternative (GetEventType()) + + case(EV_START_MUSIC){ + stageStart = true; + ObjSound_Play(objBGM); + } + + case(EV_BOSS_MUSIC){ + bossStart = true; + ObjSound_Stop(objBGM); + ObjSound_Play(objBGMBoss); + } + + case(EV_PAUSE_ENTER){ + + if (stageStart) { + if(bossStart){ + ObjSound_Stop(objBGMBoss); + } + else{ + ObjSound_Stop(objBGM); + } + } + + } + + case(EV_PAUSE_LEAVE){ + + if (stageStart) { + if(bossStart){ + ObjSound_Play(objBGMBoss); + } + else{ + ObjSound_Play(objBGM); + } + } + + } + +} + +@Initialize{ + + SetCommonDataPtr(POINTER_CHAIN, 1); + SetCommonDataPtr(POINTER_CHAINGAUGE, 0); + SetCommonDataPtr(POINTER_SPECIALAMMO, 100); + SetCommonDataPtr(POINTER_SPECIALCHECK, false); + SetCommonDataPtr(POINTER_CHAINCHECK, false); + + SetCommonData("Flying Defeated", 0); + SetCommonData("Ground Defeated", 0); + //SetCommonData("IsBomb", false); + SetCommonData("Rank", 1); + + if(!IsCommonDataAreaExists("PIV")){ + CreateCommonDataArea("PIV"); + SetAreaCommonData("PIV", "currentvalue", 1000); + SetAreaCommonData("PIV", "ChainAmount", 1); + } + else{ + SetAreaCommonData("PIV", "ChainAmount", 1); + SetAreaCommonData("PIV", "currentvalue", 1000); + } + + SetPlayerLife(GetAreaCommonData("Config", "StartingLife", 3)); + + SetAutoDeleteObject(true); + + // 0: Yal, 1: Wareya + //SetAreaCommonData("Config", "BGMSelect", "Wareya"); + + /* + if(GetAreaCommonData("Config", "BGMSelect", 0) == 1){ + ObjSound_Load(objBGM, "script/game/resourceLib/BossTheme_Wareya1.ogg"); + ObjSound_SetLoopTime(objBGM, 1.644, 51.110); + } + + else{ + ObjSound_Load(objBGM, "script/game/resourceLib/BossTheme_Yal.ogg"); + ObjSound_SetLoopTime(objBGM, 0.001, 92.81); + } + */ + + InitiateData(); + + ObjSound_Load(objBGM, "script/Jam10/resourceLib/StageTheme.mp3"); + ObjSound_SetSoundDivision(objBGM, SOUND_BGM); + ObjSound_SetResumeEnable(objBGM, true); + ObjSound_SetLoopEnable(objBGM, true); + ObjSound_SetLoopTime(objBGM, 22.72, 79.52); + + ObjSound_Load(objBGMBoss, "script/Jam10/resourceLib/BossTheme.mp3"); + ObjSound_SetSoundDivision(objBGMBoss, SOUND_BGM); + ObjSound_SetResumeEnable(objBGMBoss, true); + ObjSound_SetLoopEnable(objBGMBoss, false); + + ObjSound_SetVolumeRate(objBGMBoss, 100*BGMRate); + ObjSound_SetVolumeRate(objBGM, 100*BGMRate); + + PluralTask(); + +} + +@MainLoop{ + yield; +} + +@Finalize +{ +} + + +task InitiateData(){ + + DATA_PLAYER = GetPlayerReplayName(); + DATA_DIFFICULTY = GetCommonData("Difficulty", "Standard"); + +} + +/* TO DO: + ++ Single *syncing* - ensure that the boss stays at the same position +*/ +// Task to handle the plural's boss scene + +task PluralTask(){ + // Registering individual singles + + ObjEnemyBossScene_Add(obj, 0, csd ~ "NarumiSTG.dnh"); + ObjEnemyBossScene_LoadInThread(obj); + + _ScrollBackground(); + + // Loading and registering the boss scene + ObjEnemyBossScene_Regist(obj); + + async{ + while(GetPlayerState() != STATE_END){yield;} + ObjSound_Stop(objBGM); + ObjSound_Stop(objBGMBoss); + } + + while(!Obj_IsDeleted(obj)){ + yield; + } + + ObjSound_Stop(objBGM); + ObjSound_Stop(objBGMBoss); + stageStart = false; + bossStart = false; + + //_ExplosionEffect(GetCommonData("Boss Position X", STG_WIDTH/2), GetCommonData("Boss Position Y", STG_WIDTH/2), PetalEffect); + + if(!IsReplay() & LifeStart <= 3){ + + int highScore = GetAreaCommonData("Data_" ~ DATA_PLAYER, "HighScore_" ~ DATA_DIFFICULTY, 0); + int curScore = trunc(GetCommonData("Run Score", 0)/10)*10; + + if(curScore > highScore){SetAreaCommonData("Data_" ~ DATA_PLAYER, "HighScore_" ~ DATA_DIFFICULTY, curScore);} + else{} + + } + + string savefile = ""; + + if (DATA_PLAYER == "Narumi") {savefile = "data_Pl0.dat";} + else if (DATA_PLAYER == "Kouryuu") {savefile = "data_Pl1.dat";} + else {savefile = "data_ERROR.dat";} + + SaveCommonDataAreaA2("Data_" ~ DATA_PLAYER, "script/Jam10/" ~ savefile); + + SetAutoDeleteObject(true); + CloseScript(GetOwnScriptID()); +} \ No newline at end of file diff --git a/script/Jam10/GunnerParade.dnh b/script/Jam10/GunnerParade.dnh new file mode 100644 index 0000000..bc9bdf2 --- /dev/null +++ b/script/Jam10/GunnerParade.dnh @@ -0,0 +1,1972 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["Gunner Parade"] +#Text["This bitch empty - would you like to yeet?"] +#System["script/KevinSystem/Kevin_System.txt"] + +int imgCharacter = _Create2DImage("script/GunnerParade/PackageLib/Character_Kouda.png", [0, 0, 900, 1080]); +int imgTitle = _Create2DImage("script/GunnerParade/PackageLib/Boss_Title.png", [0, 0, 1600, 1080]); + +ObjRender_SetAlpha(imgCharacter, 0); +ObjRender_SetAlpha(imgTitle, 0); + +float rank = 1; // Increases through time + +let RANK_PTR = LoadCommonDataValuePointer("Rank", 1); + +let objScene = GetEnemyBossSceneObjectID(); +let csd = GetCurrentScriptDirectory(); + +let bossObj; + +float bossX = 0; +float bossY = 0; +float playerY = 0; +float playerX = 0; + +bool bossIntro = false; + +let spellsnd = ObjSound_Create(); +let bossdiesnd = ObjSound_Create(); + +int[] enmFly = []; +int[] enmGround = []; + +int[] rankAvg = []; + +let POINTER_CHAIN = LoadAreaCommonDataValuePointer("PIV", "ChainAmount", 1); + +//let SYSTEMID_PTR_2 = LoadAreaCommonDataValuePointer("ScriptID", "SystemID", 0); + +// Includes ahoy + +#include "script/KevinSystem/Universal_Lib.txt" +#include "script/GunnerParade/GunnerParade_EnmLib.dnh" +#include "script/GunnerParade/GunnerParade_ConstLib.dnh" +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" + +@Initialize { + + //SetIntersectionVisualization(true); + + SetAutoDeleteObject(true); + + SetCommonData("Rank", clamp(GetCommonData("Rank", 1), RANK_MIN, RANK_MAX)); + //difficultySelect = _InitDifficulty(difficultySelect); + + //difficultySelect = 2; // debug + + if(!IsCommonDataAreaExists("PIV")){ + CreateCommonDataArea("PIV"); + SetAreaCommonData("PIV", "currentvalue", 10000); + } + else{} + + // Create the boss object itself + bossObj = ObjEnemy_Create(OBJ_ENEMY_BOSS); + ObjEnemy_Regist(bossObj); + + ObjMove_SetPosition(bossObj, STG_WIDTH/2, -256); + + ObjEnemy_SetDamageRate(bossObj, 0, 0); + + _RenderBossFight(bossObj); + SetEnemyAutoDeleteClip(165, 257, 165, 256); + + //testTask(); + + groundTask(); + flyingTask(); + UpdateDrops(); + + bossFight(); + + curEnmManage(); + + //SetCommonData("Rank", 9); + + //_FadeInvincibility(bossObj, 150, 150, 1); + //endingnew(); +} + +@Event { + + alternative(GetEventType()) + + case(EV_REQUEST_LIFE) { + SetScriptResult(HP_MAX); + } + + case(EV_REQUEST_IS_DURABLE_SPELL) { + SetScriptResult(false); + } + + case(EV_REQUEST_TIMER) { + SetScriptResult(STAGE_LENGTH); + //SetScriptResult(BOSS_LENGTH+5); + } + +} + +@MainLoop { + + playerY = GetPlayerY(); + playerX = GetPlayerX(); + //The player position is ALWAYS UPDATED + + bossX = ObjMove_GetX(bossObj); + bossY = ObjMove_GetY(bossObj); + + ObjEnemy_SetIntersectionCircleToShot(bossObj, ObjMove_GetX(bossObj), ObjMove_GetY(bossObj), 180); + + yield; + +} + +@Finalize { + +} + +// This array contains ONLY FLYING ENEMIES + +task groundTask(){ + + wait(90); + + while(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) > BOSS_LENGTH){ + + WaveGround1(); + wait(max(5, 15-rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + WaveGround2(); + wait(max(5, 15-rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + WaveGround1A(); + wait(max(5, 15-rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + if(GetCommonData("Difficulty", "Standard") != "Novice"){ + SetCommonData("Rank", clamp(GetCommonData("Rank", 1)+1, RANK_MIN, RANK_MAX_TRUE)); + } + + else{} + + WaveGround3(); + wait(max(5, 15-rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + WaveGround4(); + wait(max(5, 15-rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + WaveGround5(); + wait(max(5, 15-rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + if(GetCommonData("Rank", 1)+1 >= 7){ + + WaveGround1A(); + wait(max(5, 15-rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + WaveGround6(); + wait(max(5, 15-rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + } + + SetCommonData("Ground Loops Cleared", GetCommonData("Ground Loops Cleared", 0)+1); + + yield; + } + +} + +task flyingTask(){ + + wait(30); + + while(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) > BOSS_LENGTH){ + + Wave1(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + Wave2(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + Wave3(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + Wave4(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + Wave5(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + Wave6(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + SetCommonData("Flying Loops Cleared", GetCommonData("Flying Loops Cleared", 0)+1); + + yield; + } + +} + +task curEnmManage(){ + + SetCommonData("Flying Loops Cleared", 0); + SetCommonData("Ground Loops Cleared", 0); + + RankManagement(); + + int[] allEnm = []; + + while(true){ + enmGround = []; + enmFly = []; + allEnm = GetIntersectionRegistedEnemyID(); + for each (int enm in ref allEnm){ + if(Obj_GetRenderPriorityI(enm) <= 37){enmGround ~= [enm];} + else if(Obj_GetRenderPriorityI(enm) >= 38 && Obj_GetRenderPriorityI(enm) < 41){enmFly ~= [enm];} + else{} + } + wait(10); + } + +} + +task _BossExplosion(){ + + float enmX = 0, enmY = 0; + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + + enmX = ObjMove_GetX(bossObj); enmY = ObjMove_GetY(bossObj); + + yield; + + } + + //NotifyEventAll(EV_DROP_POINT_ENEMY, [enmX, enmY], timer, maxTimer, minPoint, maxPoint); + + DeleteShotAll(TYPE_ALL, TYPE_ITEM); + SetPlayerInvincibilityFrame(300); + ObjSound_Play(bossBoom); + Obj_SetRenderPriorityI(bossObj, 30); + NotifyEvent(GetCommonDataPtr(SYSTEMID_PTR, 0), EV_EXPLODE, [enmX, enmY]); + + _ObjShake(bossObj, 190, 60); + + loop(30){ + //LoadEx(bossBoom, "script/game/resourceLib/bigBoom.ogg", 30 * SFXVol); + ObjSound_Play(bossBoom); + NotifyEvent(GetCommonDataPtr(SYSTEMID_PTR, 0), EV_EXPLODE, [bossX+rand(-240, 240), bossY+rand(-150, 150)]); + wait(6); + } + + ObjMove_SetDestAtFrame(bossObj, bossX, STG_HEIGHT+512, 120, LERP_ACCELERATE); + + float ang = ObjRender_GetAngleZ(bossObj); + + ascent(i in 0..120){ + ObjRender_SetAngleZ(bossObj, Interpolate_Accelerate(ang, ang+180, i/120)); + yield; + } + + //wait(); + + _EndShake(120, 90); + + loop(120){ + NotifyEvent(GetCommonDataPtr(SYSTEMID_PTR, 0), EV_EXPLODE, [bossX+rand(-240, 240), STG_HEIGHT+rand(0, -150)]); + } + + ObjSound_Play(bossBoom); + + EndBonus(); + + //_ScorePopup(float enmX, float enmY, int pointNum, int pivNum); + + // NotifyEvent is faster than NotifyEventAll, considering how the item event will be called many times. + +} + +task EndBonus(){ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + //WriteLog(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER)); + //wait(30); + yield; + } + + ObjEnemy_SetLife(bossObj, -1); + + let timer = ObjEnemyBossScene_GetInfo(objScene, INFO_TIMERF); + //WriteLog(timer); + + // Bonus Calculations: + + // (Time Remaining + Ground Loops Cleared + Flying Loops Cleared + Average Rank) * 10000 + + function _CreateBonusText(float x, y, fontSize, int colorBorder, string text){ + + int objText = CreateTextObject( + + x, y, fontSize, + "", "Origami Mommy", + 0xFFFFFF, 0xFFFFFF, + colorBorder, 4, + 71 + + ); + + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER); + + TTextScroll(objText, text); + + } + + wait(120); + + float rankAvgFinal = 0; + float rankSum = 0; + + ascent(i in -1..length(rankAvg)-1){ + rankSum += rankAvg[i]; + } + + rankAvgFinal = rankSum/length(rankAvg); + + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2-220, 30, 0xCF007A, "LIVES REMAINING: " ~ IntToString(GetPlayerLife())); + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2-180, 30, 0x3500CF, "TIME REMAINING: " ~ vtos("5.2f", timer/60)); + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2-140, 30, 0xCF6100, "ENEMIES DEFEATED: " ~ IntToString(GetCommonDataPtr(GROUNDENM_PTR, 0) + GetCommonDataPtr(FLYINGENM_PTR, 0))); + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2-100, 30, 0xCF0000, "AVERAGE RANK LV: " ~ vtos("5.2f", rankAvgFinal)); + + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2, 30, 0xFFA300, "END BONUS:"); + + wait(120); + + float multiplierBonus = (GetPlayerLife() + timer/60 + GetCommonDataPtr(GROUNDENM_PTR, 0)/5 + GetCommonDataPtr(FLYINGENM_PTR, 0)/5 + rankAvgFinal) * 30; + + int scoreBonus = trunc ( (multiplierBonus * 100000) / 10 ) * 10; + + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2+60, 60, 0xFFA300, DigitToCommaArray(scoreBonus)); + AddScore(scoreBonus); + + wait(60); + + if(!IsReplay()){SetCommonData("Run Score", GetScore());} + else{SetCommonData("Run Score", 0);} + + Obj_Delete(bossObj); + CloseScript(GetOwnScriptID()); + +} + +task RankManagement(){ + + //SetCommonData("Rank", 9); + //SetCommonData("Rank", 10); + // Rank increase + let textRank = CreateTextObject( + STG_WIDTH-15, STG_HEIGHT/14, 28, + "RANK:", "Origami Mommy", + 0xFFFFFF, 0xFFFFFF, + 0xAE22FF, 5, + 71 + ); + + ObjText_SetHorizontalAlignment(textRank, ALIGNMENT_RIGHT); + + async{ + while(true){ + rank = trunc(GetCommonData("Rank", 1)); + if(rank >= RANK_MAX){ObjText_SetText(textRank, "RANK LV [font sz=45 oc=(193, 0, 99)]MAX");} + else{ObjText_SetText(textRank, "RANK LV [font sz=45 oc=(193, 0, 99)]" ~ IntToString(rank));} + //SetCommonData("Rank", 9); + wait(45); + } + } + + async{ + while(true){ + if(ObjMove_GetY(GetPlayerObjectID()) < GetStgFrameHeight()/6){ + ObjRender_SetAlpha(textRank, 60); + } + else{ + ObjRender_SetAlpha(textRank, 255); + } + yield; + } + } + + async{ + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + rankAvg ~= [rank]; + wait(60); + } + } + + // Per frame rank increase. +1 rank per 10 seconds (+0.1 rank per second, +1/600 rank per frame), rank 10 at 100 seconds if no specials, bombs or deaths happen + + async{ + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + SetCommonDataPtr(RANK_PTR, clamp(GetCommonDataPtr(RANK_PTR, 1)+1/600, RANK_MIN, RANK_MAX_TRUE)); + yield; + } + } + + // Rank on HUD + + async{ + let textRank = CreateTextObject( + 1500, 660, 48, + "", "Origami Mommy", + 0xFF9294, 0xFFFFFF, + 0x8F0507, 8, + 19 + ); + + ObjText_SetHorizontalAlignment(textRank, ALIGNMENT_CENTER); + + let textRankRange = CreateTextObject( + 1820, 618, 24, + "", "Unispace", + 0xA9FFD0, 0xFFFFFF, + 0x8F0507, 2, + 19 + ); + + while(true){ + ObjText_SetText(textRank, IntToString(rank)); + ObjText_SetText(textRankRange, "LV." ~ IntToString(RANK_MIN) ~ "[r][font oy=4 tc=(255, 114, 189)]LV." ~ IntToString(RANK_MAX_TRUE) ~ "[r][font oy=8 tc=(255, 147, 138)]" ~ rtos("00.00", GetCommonData("Rank", 1))); + yield; + } + } + +} + +task testTask(){ + + wait(15); + + while(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) > 20){ + + /* + Wave1(); + Wave2(); + + Wave4(); + Wave5(); + */ + + WaveGround6(); + + wait(15); + + SetCommonData("Rank", clamp(GetCommonData("Rank", 1)+1, 1, RANK_MAX)); + SetCommonData("Ground Loops Cleared", GetCommonData("Ground Loops Cleared", 0)+1); + SetCommonData("Flying Loops Cleared", GetCommonData("Flying Loops Cleared", 0)+1); + + yield; + } + +} + +///////////// BOSS HANDLING ///////////// + +task bossFight(){ + + while(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMERF) > BOSS_LENGTH*60){ + + yield; + + } + + bossIntro = true; + + BossIntro(); + BossPhase1(); + BossPhase2(); + BossPhase3(); + + // Umbrella waves + + return; + +} + +function BossIntro(){ + + bool bossCurrentlyIntro = true; + + async{ + int timer = ObjEnemyBossScene_GetInfo(objScene, INFO_TIMERF); + while(bossCurrentlyIntro){ + ObjEnemyBossScene_SetSpellTimer(objScene, timer); + SetForbidPlayerShot(true); + SetForbidPlayerSpell(true); + ObjEnemy_SetDamageRate(bossObj, 0, 0); + yield; + } + + SetForbidPlayerShot(false); + SetForbidPlayerSpell(false); + ObjEnemy_SetDamageRate(bossObj, 0, 0); + + } + + SetPlayerInvincibilityFrame(180); + DeleteShotAll(TYPE_ALL, TYPE_ITEM); + + Obj_SetRenderPriorityI(imgCharacter, 81); + Obj_SetRenderPriorityI(imgTitle, 81); + + ObjRender_SetScaleXYZ(imgCharacter, 1); + ObjRender_SetScaleXYZ(imgTitle, 0.5); + + ObjRender_SetPosition(imgCharacter, 1920/2, 1080/2, 1); + ObjRender_SetPosition(imgTitle, 1920/2, 1080/2, 1); + + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, STG_HEIGHT/4, 30, LERP_DECELERATE); + wait(30); + + ascent(i in 0..30){ + + int a = i; + if(a > 15){a = 15;} + + ObjRender_SetX(imgCharacter, FUNC_LERP_DECEL(1920/2, 1920/2 + 240, i/30)); + ObjRender_SetX(imgTitle, FUNC_LERP_DECEL(1920/2, 1920/2 - 240, i/30)); + + ObjRender_SetAlpha(imgCharacter, FUNC_LERP_DECEL(0, 255, a/15)); + ObjRender_SetAlpha(imgTitle, FUNC_LERP_DECEL(0, 255, a/15)); + + yield; + + } + + ascent(i in 0..75){ + + ObjRender_SetX(imgCharacter, FUNC_LERP_LINEAR(1920/2+240, 1920/2+275, i/75)); + ObjRender_SetX(imgTitle, FUNC_LERP_LINEAR(1920/2-240, 1920/2-275, i/75)); + + yield; + + } + + ascent(i in 0..30){ + + int a = i; + if(a > 15){a = 15;} + + ObjRender_SetX(imgCharacter, FUNC_LERP_LINEAR(1920/2+275, 1920/2+600, i/30)); + ObjRender_SetX(imgTitle, FUNC_LERP_LINEAR(1920/2-275, 1920/2-600, i/30)); + + ObjRender_SetAlpha(imgCharacter, FUNC_LERP_DECEL(255, 0, a/15)); + ObjRender_SetAlpha(imgTitle, FUNC_LERP_DECEL(255, 0, a/15)); + + yield; + + + } + + bossCurrentlyIntro = false; + + return; + +} + +function BossPhase1(){ + + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, STG_HEIGHT/4, 60, LERP_DECELERATE); + wait(10); + + _FadeInvincibility(bossObj, 90, 90, 0.25); + + // Bird columns moving horizontally, leaving behind 2-way bullet lines + + int bulletNum = FUNC_LERP_LINEAR(3, 5, rank/RANK_MAX); + float birdNum = FUNC_LERP_LINEAR(5, 8, rank/RANK_MAX); + float bulletSpd = FUNC_LERP_ACCEL(8, 12, rank/RANK_MAX); + float birdMaxSpd = FUNC_LERP_ACCEL(12, 16, rank/RANK_MAX); + int birdAccelTime = FUNC_LERP_ACCEL(30, 20, rank/RANK_MAX); + int spawnDel = FUNC_LERP_LINEAR(90, 75, rank/RANK_MAX); + + // Spiral - use W3 parameters + + int linenum = FUNC_LERP_LINEAR(4, 7, rank/RANK_MAX); + int dense = FUNC_LERP_LINEAR(14, 18, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(5, 3, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(10, 13, rank/RANK_MAX); + float angStart = rand(0, 360); + + task _SummonBird(float startX, startY){ + + float angMove = startX < 0 ? 0 : 180; + float destMove = startX < 0 ? STG_WIDTH/13 : 12*STG_WIDTH/13; + + int enm = _SmallWitch( + 40, birdAccelTime*999, + startX, startY + ); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + ObjMove_SetDestAtFrame(enm, destMove, startY, birdAccelTime, LERP_DECELERATE); + wait(birdAccelTime); + ObjMove_AddPatternA2(enm, 0, NO_CHANGE, NO_CHANGE, birdMaxSpd/birdAccelTime, birdMaxSpd, 0); + + } + + ObjRender_SetAngleZ(enm, angMove); + + wait(birdAccelTime*1.5); + + float ang = angMove + rand(-5, 5); + + ascent(i in 0..bulletNum) + { + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), FUNC_LERP_LINEAR(bulletSpd/1.4, bulletSpd, i/bulletNum), GetAngleToPlayer(enm), KEV_BALL_PINK, 5); + + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 5); + + //int bullet2 = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), FUNC_LERP_LINEAR(bulletSpd/2, bulletSpd, i/bulletNum), GetAngleToPlayer(enm), KEV_BALL_PINK, 5); + + //_BulletRescale(bullet2, 0.75, true, 0.25); + //_Delay(bullet2, 5); + + }; + + ObjEnemy_SetDamageRate(enm, 200, 200); + + } + + PhaseBonusCalculation(PHASE1_LIMIT, "[font oc=(98, 0, 164) wg=800]Hitchcock Trap"); + + async{ + + int i = 180; + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE1_LIMIT){ + + int shot = CreateFan(bossObj, 1, KEV_LEAF_ORANGE, linenum, + angStart+i*1*360/dense, 0, spd/1.5, spd, + 0.75, + 0, 0, + PATTERN_FAN, false + ); + int shot2 = CreateFan(bossObj, 1, KEV_LEAF_ORANGE, linenum, + angStart+(180+angStart)+i*(-1)*360/dense, 0, spd/1.5, spd, + 0.75, + 0, 0, + PATTERN_FAN, false + ); + + Shoot2; + + i++; + wait(del); + + yield; + + } + + } + + async{ + float ang = 180; + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE1_LIMIT){ + + ObjMove_SetX(bossObj, STG_WIDTH/2 + STG_WIDTH/6 * sin(ang)); + ang += 1.5; + yield; + + } + } + + float offset = rand(-STG_HEIGHT/16, STG_HEIGHT/16); + float y1 = 0 - offset; + float y2 = STG_HEIGHT - offset; + + async{ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE1_LIMIT){ + + ChargeSFX; + // From the left + ascent(i in 0..birdNum){ + _SummonBird(-96, FUNC_LERP_LINEAR(y1, y2, i/birdNum)); + } + + wait(spawnDel); + + offset = rand(-STG_HEIGHT/12, STG_HEIGHT/12); + y1 = 0 - offset; + y2 = STG_HEIGHT - offset; + + ChargeSFX; + ascent(i in 0..birdNum){ + _SummonBird(STG_WIDTH+96, FUNC_LERP_LINEAR(y1, y2, i/birdNum)); + } + + wait(spawnDel); + + yield; + + } + + } + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE1_LIMIT){ + + yield; + + } + + ObjEnemy_SetDamageRate(bossObj, 0, 0); + DeleteShotAll(TYPE_ALL, TYPE_ITEM); + + wait(30); + + return; + +} + +function BossPhase2(){ + + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, STG_HEIGHT/4, 60, LERP_DECELERATE); + + _FadeInvincibility(bossObj, 90, 90, 0.25); + + wait(30); + + // FISH + + int bulletNum = FUNC_LERP_LINEAR(9, 12, rank/RANK_MAX); + float bulletSpd = FUNC_LERP_ACCEL(8, 12, rank/RANK_MAX); + float fishMaxSpd = FUNC_LERP_ACCEL(14, 18, rank/RANK_MAX); + int fishAccelTime = FUNC_LERP_ACCEL(30, 20, rank/RANK_MAX); + int spawnDel1 = FUNC_LERP_LINEAR(10, 6, rank/RANK_MAX); + int spawnDel2 = FUNC_LERP_LINEAR(60, 45, rank/RANK_MAX); + + // Bullet lines + + int linenum = FUNC_LERP_LINEAR(12, 18, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(4, 2, rank/RANK_MAX); + int del2 = FUNC_LERP_ACCEL(8, 5, rank/RANK_MAX); + int bulletDel = FUNC_LERP_ACCEL(10, 5, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(9, 11, rank/RANK_MAX); + float ang = rand(80, 100); + + task _SummonFish(float startX){ + + float angMove = atan2((-48 - playerY), (startX - playerX))+180; + + int enm = _Fish( + 39, fishAccelTime*50, + startX, -48 + ); + + ObjEnemy_SetDamageRate(enm, 0, 0); + ObjMove_SetSpeed(enm, fishMaxSpd); + ObjMove_SetAngle(enm, angMove); + ObjRender_SetAngleZ(enm, angMove+90); + + float ang = angMove; + + Shoot2; + + ascent(i in 0..bulletNum) + { + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), 0, ang, KEV_LEAF_LAVENDER, 5); + + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 5); + + ObjMove_AddPatternA2(bullet, fishAccelTime, NO_CHANGE, NO_CHANGE, FUNC_LERP_LINEAR(bulletSpd, bulletSpd*1.5, i/bulletNum)/fishAccelTime, FUNC_LERP_LINEAR(bulletSpd, bulletSpd*1.5, i/bulletNum), 0); + + wait(del); + + }; + + ObjEnemy_SetDamageRate(enm, 200, 200); + + } + + PhaseBonusCalculation(PHASE2_LIMIT, "[font oc=(98, 0, 164) wg=800]Fish Out of Water"); + + async{ + + float angA = ang; + int i = 0; + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE2_LIMIT){ + + float val1 = i % 2 == 0 ? -384 : STG_WIDTH + 384; + float val2 = i % 2 == 0 ? STG_WIDTH + 384 : -384; + + Shoot1; + + ascent(i in 0..linenum){ + + int bullet = CreateShotA1( + FUNC_LERP_LINEAR(val1, val2, i/linenum), -96, + spd, angA, KEV_BALL_AQUA, 5 + ); + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 5); + wait(del); + + } + + i++; + + } + + } + + async{ + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE2_LIMIT){ + + ascent(i in 0..5){ + _SummonFish(i * STG_WIDTH/5); + wait(spawnDel1); + } + + wait(spawnDel2); + + ascent(i in 0..5){ + _SummonFish((5-i) * STG_WIDTH/5); + wait(spawnDel1); + } + + wait(spawnDel2); + + } + } + + float offset = rand(-STG_HEIGHT/8, STG_HEIGHT/8); + float y1 = 0 - offset; + float y2 = STG_HEIGHT - offset; + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE2_LIMIT){ + + yield; + + } + + ObjEnemy_SetDamageRate(bossObj, 0, 0); + DeleteShotAll(TYPE_ALL, TYPE_ITEM); + + wait(45); + + return; + +} + +function BossPhase3(){ + + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, STG_HEIGHT/5, 60, LERP_DECELERATE); + + PhaseBonusCalculation(PHASE3_LIMIT, "[font oc=(98, 0, 164) wg=800]Paving a Rainbow Sky"); + + _FadeInvincibility(bossObj, 90, 90, 0.25); + + wait(30); + + float numKilled = 0; + + // BIRD + + float bulletNum = FUNC_LERP_LINEAR(8, 12, rank/RANK_MAX); + float bulletSpd = FUNC_LERP_ACCEL(6.25, 7.25, rank/RANK_MAX); + float birdWvel = FUNC_LERP_ACCEL(1.2, 2, rank/RANK_MAX); + int bulletDel = FUNC_LERP_LINEAR(10, 5, rank/RANK_MAX); + int bulletWait = FUNC_LERP_LINEAR(45, 35, rank/RANK_MAX); + float birdSpd = FUNC_LERP_ACCEL(9, 11.2, rank/RANK_MAX); + float birdNum = FUNC_LERP_LINEAR(10, 15, rank/RANK_MAX); + int spawnDel = FUNC_LERP_ACCEL(80, 60, rank/RANK_MAX); + + // Bullet lines + + int linenum = FUNC_LERP_LINEAR(14, 17, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(4, 2, rank/RANK_MAX); + int del2 = FUNC_LERP_ACCEL(8, 5, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(9, 11, rank/RANK_MAX); + float ang = rand(80, 100); + + async{ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE3_LIMIT){yield;} + + ObjEnemy_SetDamageRate(bossObj, 0, 0); + DeleteShotAll(TYPE_ALL, TYPE_ITEM); + + _BossExplosion(); + + } + + task _SummonBirdEx(float startAng, float wvel, int num){ + + int umbrella = _SmallWitch( + 41, bulletDel * bulletNum, + bossX, bossY + ); + + bool isFinishMove = false; + + ObjMove_SetAngle(umbrella, startAng); + ObjRender_SetAngleZ(umbrella, startAng); + + ObjMove_SetAngularVelocity(umbrella, wvel); + + ObjMove_SetSpeed(umbrella, birdSpd); + + ObjMove_AddPatternA2(umbrella, 60, NO_CHANGE, NO_CHANGE, NO_CHANGE, NO_CHANGE, wvel/10); + + async{ + while(!Obj_IsDeleted(umbrella)){ + ObjRender_SetAngleZ(umbrella, ObjMove_GetAngle(umbrella)); + yield; + } + numKilled++; + ObjEnemy_SetDamageRate(bossObj, numKilled * 2.5, numKilled * 2.5); // 33 enemies put dmg rate to 100 + } + + int num2 = 0; + + ascent(i in 0..num){ + + float lerpNum1 = i; + float lerpNum2 = num; + + ObjEnemy_SetDamageRate(umbrella, FUNC_LERP_LINEAR(10, 50, lerpNum1/lerpNum2), FUNC_LERP_LINEAR(10, 50, lerpNum1/lerpNum2)); + + int color = KEV_LEAF_RED + num2; + + int bullet = CreateShotA1(ObjMove_GetX(umbrella), ObjMove_GetY(umbrella), 0, wvel < 0 ? ObjMove_GetAngle(umbrella) : ObjMove_GetAngle(umbrella), color, 5); + + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0 || Obj_IsDeleted(umbrella)){Obj_Delete(bullet);} + else{ + _Delay(bullet, 5); + _BulletRescale(bullet, 0.75, true, 0.25); + BulletAction(bullet, lerpNum1, lerpNum2); + Shoot1; + } + + wait(bulletDel); + + num2++; + if (num2 > (KEV_BALL_PINK - KEV_BALL_RED)){num2 = 0;} + } + + task BulletAction(ID, lerpNum1, lerpNum2){ + + while(!isFinishMove){yield;} + + if(Obj_IsDeleted(ID)){return;} + else{ + ObjMove_AddPatternA2(ID, 0, NO_CHANGE, NO_CHANGE, FUNC_LERP_LINEAR(bulletSpd/1.5, bulletSpd, lerpNum1/lerpNum2)/FUNC_LERP_LINEAR(bulletWait, bulletWait/1.5, lerpNum1/lerpNum2), FUNC_LERP_LINEAR(bulletSpd/1.5, bulletSpd, lerpNum1/lerpNum2), 0); + } + + } + + isFinishMove = true; + + ObjEnemy_SetDamageRate(umbrella, 100, 100); + + } + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE3_LIMIT){ + + float randAng = rand(0, 360); + + ascent(i in 0..birdNum){ + _SummonBirdEx(i * 360/birdNum + randAng, birdWvel, bulletNum); + } + + wait(spawnDel); + + randAng = rand(0, 360); + + ascent(i in 0..birdNum){ + _SummonBirdEx(i * 360/birdNum + randAng, -birdWvel, bulletNum); + } + + wait(spawnDel); + + } + + return; + +} + +task PhaseBonusCalculation(int HPthreshold, string spellName){ + + int curRank = rank; + int scoreBase = 1000000 * curRank; + int scoreBonus = scoreBase * GetCommonDataPtr(POINTER_CHAIN, 1); + int i = 0; // 20 seconds + + function _CreateBonusText(float x, y, fontSize, int colorBorder, string text){ + + let objText = CreateTextObject( + + x, y, fontSize, + text, "Unispace", + 0xFFFFFF, 0xFFFFFF, + colorBorder, fontSize/10, + 71 + + ); + + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_RIGHT); + + return objText; + + } + + let scoreText = _CreateBonusText(STG_WIDTH-12, STG_HEIGHT/9+12, 32, 0x000000, ""); + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > HPthreshold){ + + scoreBase = trunc(Interpolate_Smooth(1000000 * curRank, 100000 * curRank, i/1200)/10)*10; + i = min(1200, i+1); + + scoreBonus = scoreBase * GetCommonDataPtr(POINTER_CHAIN, 1); + + ObjText_SetText(scoreText, spellName ~ "[r]BONUS: " ~ DigitToCommaArray(scoreBase) ~ "[font sz=30] x [font clr][font oc=(255, 134, 81)]" ~ rtos("00.00", GetCommonDataPtr(POINTER_CHAIN, 1))); + + yield; + + } + + AddScore(scoreBonus); + + async{ + + ObjText_SetText(scoreText, "[font sz=32 oc=(164, 0, 90)]SCORE BONUS:[r][font sz=50 wg=800 oc=(255, 136, 0)]" ~ DigitToCommaArray(trunc(scoreBonus/10)*10)); + + ChargeBreakSFX; + + wait(60); + + Obj_Delete(scoreText); + + } + +} + +///////////// ENEMY HANDLING (NOT BOSS) ///////////// + +function WaveGround1(){ + + float speedMove = baseMoveSpeed1L * (1 + MoveSpeedRankMultiplierH * rank); + int invin = FUNC_LERP_DECEL(WG1_invinTimeMax, WG1_invinTimeMin, rank/RANK_MAX); + + _SignPlatform1( + 34, invin, + STG_WIDTH/4, -128, speedMove + ); + + wait(invin); + + while(length(enmGround) > 1){yield;} + + _SignPlatform1( + 34, invin, + 3*STG_WIDTH/4, -128, speedMove + ); + + wait(invin); + + while(length(enmGround) > 1){yield;} + + return; + +} + +function WaveGround1A(){ + + float speedMove = baseMoveSpeed1L * (1 + MoveSpeedRankMultiplierL * rank); + int invin = FUNC_LERP_DECEL(WG1A_invinTimeMax, WG1A_invinTimeMin, rank/RANK_MAX); + int num = FUNC_LERP_DECEL(WG1A_bulletNumMin, WG1A_bulletNumMax, rank/RANK_MAX); + float spd = FUNC_LERP_DECEL(WG1A_bulletSpdMin, WG1A_bulletSpdMax, rank/RANK_MAX); + float del = FUNC_LERP_DECEL(WG1A_bulletDelayMin, WG1A_bulletDelayMax, rank/RANK_MAX); + + int[] signs1 = _SignPlatform1A( + 34, invin, + 2*STG_WIDTH/7-64, -128, speedMove + ); + + for each (int sign in ref signs1){ + Atk(sign); + } + + int[] signs2 = _SignPlatform1A( + 34, invin, + 5*STG_WIDTH/7+64, -128, speedMove + ); + + for each (int sign in ref signs2){ + Atk(sign); + } + + task Atk(int ID){ + + async{ + while(!Obj_IsDeleted(ID) && ObjMove_GetY(ID) <= STG_HEIGHT - 128 && GetObjectDistance(ID, GetPlayerObjectID()) > popcornHitbox * 2){ + + CreateFan( + ID, num, KEV_BALL_PINK, 1, + GetAngleToPlayer(ID), 2.25, spd, spd/1.5, 0.75, + ObjMove_GetX(ID), ObjMove_GetY(ID), + PATTERN_FAN, false + ); + + wait(del); + + } + } + + } + + wait(invin); + + while(length(enmGround) > 1){yield;} + + return; + +} + +function WaveGround2(){ + + float speedMove = baseMoveSpeedVL * (1 + MoveSpeedRankMultiplierL * rank); + int invin = FUNC_LERP_DECEL(WG2_invinTimeMax, WG2_invinTimeMin, rank/RANK_MAX); + + int del = FUNC_LERP_DECEL(WG2_bulletDelayMax, WG2_bulletDelayMin, rank/RANK_MAX); + int num = FUNC_LERP_DECEL(WG2_bulletNumMin, WG2_bulletNumMax, rank/RANK_MAX); + float spd = FUNC_LERP_DECEL(WG2_bulletSpdMin, WG2_bulletSpdMax, rank/RANK_MAX); + float space = FUNC_LERP_DECEL(WG2_angRangeMin, WG2_angRangeMax, rank/RANK_MAX); + + float aimAng = 0; + + task Atk(int ID){ + + async{ + while(!Obj_IsDeleted(ID) && ObjMove_GetY(ID) <= STG_HEIGHT * 6/7 && GetObjectDistance(ID, GetPlayerObjectID()) > popcornHitbox * 3){ + + float posX = 128 * cos(GetAngleToPlayer(ID)); + float posY = 128 * sin(GetAngleToPlayer(ID)); + + CreateFan( + ID, num, KEV_FIRE_RED, 1, + GetAngleToPlayer(ID), space, spd, spd/1.5, 1, + posX, posY, + PATTERN_FAN, false + ); + + wait(del); + + } + } + + while(!Obj_IsDeleted(ID)){ + ObjRender_SetAngleZ(ID, atan2(playerY - ObjMove_GetY(ID), playerX - ObjMove_GetX(ID))); + aimAng = atan2(playerY - ObjMove_GetY(ID), playerX - ObjMove_GetX(ID)); + yield; + } + } + + int[] enmArr = _CreateCannonBush( + 35, invin, + 2*STG_WIDTH/7, -128, speedMove + ); + + for each(int enm in ref enmArr){ + Atk(enm); + } + + wait(invin); + + while(length(enmGround) > 0){yield;} + + int[] enmArr2 = _CreateCannonBush( + 34, invin, + 5*STG_WIDTH/7, -128, speedMove + ); + + for each(int enm in ref enmArr2){ + Atk(enm); + } + + wait(invin); + + while(length(enmGround) > 0){yield;} + + return; + +} + +// Rybb + +function WaveGround3(){ + + float speedMove = baseMoveSpeedVL * (1 + MoveSpeedRankMultiplierVL * rank); + + int dense = FUNC_LERP_DECEL(WG3_spiralDenseMin, WG3_spiralDenseMax, rank/RANK_MAX); + int num = FUNC_LERP_DECEL(WG3_spiralNumMin, WG3_spiralNumMax, rank/RANK_MAX); + int del = FUNC_LERP_DECEL(WG3_spiralDelayMax, WG3_spiralDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_DECEL(WG3_spiralSpdMin, WG3_spiralSpdMax, rank/RANK_MAX); + + int ship = _CreateRybb( + 36, del*3, + playerX, -180, speedMove + ); + + async{ + + while(!Obj_IsDeleted(ship)){ + + if (ObjMove_GetY(ship) <= 0) {ObjEnemy_SetDamageRate(ship, 0, 0);} + else if (ObjMove_GetY(ship) <= FUNC_LERP_LINEAR(180, 60, rank/RANK_MAX)) {ObjEnemy_SetDamageRate(ship, 25, 0);} + else {ObjEnemy_SetDamageRate(ship, 100, 100);} + + yield; + + } + + } + + int i = 0; + float startAng = 0; + + while(!Obj_IsDeleted(ship)){ + + int dir = i % 2 == 0 ? 1 : -1; + float startAng = i % 2 == 0 ? rand(-5, 0) : rand(0, 5); + + ascent(i in 0..num){ + ascent(k in 0..dense){ + int bullet = CreateShotA1(ObjMove_GetX(ship), ObjMove_GetY(ship), FUNC_LERP_LINEAR(spd, spd, i/num), startAng + k * 360/dense + dir * i * 4, KEV_BALL_ORANGE, 5+i); + _BulletRescale(bullet, 0.6, true, 0.25); + _Delay(bullet, 5+i*2); + } + } + + Shoot1; + wait(del); + i++; + + } + +} + +function WaveGround4(){ + + int del = FUNC_LERP_DECEL(WG4_bulletDelayMax, WG4_bulletDelayMin, rank/RANK_MAX); + int num = FUNC_LERP_DECEL(WG4_enmNumMin, WG4_enmNumMax, rank/RANK_MAX); + float enmspd = rand(baseMoveSpeedH * (1 + MoveSpeedRankMultiplierL*rank), baseMoveSpeedVH * (1 + MoveSpeedRankMultiplierL*rank)); + float spd = FUNC_LERP_DECEL(WG4_bulletSpdMin, WG4_bulletSpdMax, rank/RANK_MAX); + int time = FUNC_LERP_DECEL(WG4_invinTimeMax, WG4_invinTimeMin, rank/RANK_MAX); + float bushspd = baseMoveSpeedVL * (1 + MoveSpeedRankMultiplierVL*rank); + + float x = 0, y = 0; + + int bussy = _CreateDangerBush( + 34, time, + STG_WIDTH/2, -128, bushspd + ); + + async{ + + wait(time/2); + + while(!Obj_IsDeleted(bussy)){ + x = ObjMove_GetX(bussy); + y = ObjMove_GetY(bussy); + yield; + } + + if( + (y > STG_HEIGHT+64) + ) + { + return; + } + // Release bussy busses + + loop(num){ + + int enm = _SmallFairy( + 38, time/2, + x, y + ); + + int debris = _CreateBushRemnant( + 35, time/2, + x, y + ); + + enmPattern(enm); + enmPattern2(debris); + + } + + task enmPattern(int ID){ + + float valueX = clamp([rand(-enmspd*1, -enmspd*0.25), rand(enmspd*0.25, enmspd*1)][rand_int(0, 1)], -12, 12); + float valueY = -enmspd * rand(1, 1.5); + + ObjMove_AddPatternB2(ID, 0, valueX, valueY, -valueX/45, -valueY/45, valueX/20, -valueY/1.25); + + while(!Obj_IsDeleted(ID) && ObjMove_GetY(ID) > 0 && ObjMove_GetY(ID) < STG_HEIGHT * 7/8){ + + if (ObjMove_GetSpeedY(ID) <= -valueY/24) {ObjEnemy_SetDamageRate(ID, 0, 0);} + else {ObjEnemy_SetDamageRate(ID, 100, 100);} + + ObjMove_SetY(ID, clamp(ObjMove_GetY(ID), 0, STG_HEIGHT+99999999)); + + int bullet = CreateShotA1(ObjMove_GetX(ID), ObjMove_GetY(ID), spd, GetAngleToPlayer(ID), KEV_BALL_LAVENDER, 5); + + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 5); + Shoot1; + + wait(del); + } + } + + task enmPattern2(int ID){ + + float valueX = clamp([rand(-enmspd*1.25, -enmspd*0.75), rand(enmspd*1.25, enmspd*0.75)][rand_int(0, 1)], -12, 12); + float valueY = -enmspd * rand(1, 1.5); + + ObjMove_AddPatternB2(ID, 0, valueX, valueY, -valueX/35, -valueY/35, valueX/12.5, -valueY); + //ObjRender_SetAlpha(ID, 160); + + while(!Obj_IsDeleted(ID)){ + + if (ObjMove_GetSpeedY(ID) <= -valueY/24) {ObjEnemy_SetDamageRate(ID, 0, 0);} + else {ObjEnemy_SetDamageRate(ID, 100, 100);} + + ObjMove_SetY(ID, clamp(ObjMove_GetY(ID), 0, STG_HEIGHT+99999999)); + + ObjRender_SetAngleZ(ID, ObjRender_GetAngleZ(ID)+3); + + yield; + + } + + } + + } + + wait(time/2); + + while(length(enmGround) > 0){yield;} + + return; +} + +function WaveGround5(){ + + float speedMove = baseMoveSpeedVL * (1 + MoveSpeedRankMultiplierVL * rank) * 0.5; + + int num = FUNC_LERP_DECEL(WG5_bulletNumMin, WG5_bulletNumMax, rank/RANK_MAX); + int del = FUNC_LERP_DECEL(WG5_bulletDelayMax, WG5_bulletDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_DECEL(WG5_bulletSpdMin, WG5_bulletSpdMax, rank/RANK_MAX); + float[] moveX = [[180, -1.5], [0, 1.5]][GetCommonData("Flying Loops Cleared", 0) % 2]; + + int ship = _CreateDecker( + 37, del*3, + playerX, -180, speedMove + ); + + async{ + if(GetCommonData("Rush", false) == true){WaveGround3();} + else{} + } + + async{ + + while(!Obj_IsDeleted(ship)){ + + ObjMove_SetSpeedY(ship, speedMove); + ObjMove_SetX(ship, STG_WIDTH/2 + STG_WIDTH/2 * cos(moveX[0])); + + if (ObjMove_GetY(ship) <= 0) {ObjEnemy_SetDamageRate(ship, 0, 0);} + else if (ObjMove_GetY(ship) <= FUNC_LERP_LINEAR(180, 60, rank/RANK_MAX)) {ObjEnemy_SetDamageRate(ship, 25, 0);} + else {ObjEnemy_SetDamageRate(ship, 100, 100);} + + moveX[0] += moveX[1]; + + yield; + + } + + } + + int i = 0; + float startAng = 0; + + while(!Obj_IsDeleted(ship)){ + + int x = i % 2 == 0 ? 64 : -64; + + ascent(i in 0..num){ + int bullet = CreateShotA1(ObjMove_GetX(ship)+x, ObjMove_GetY(ship)+160, FUNC_LERP_LINEAR(spd, spd*1.5, i/num), 90, KEV_LEAF_ORANGE, 5); + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 10); + ObjShot_SetDelayMotionEnable(bullet, true); + } + + Shoot1; + wait(del); + i++; + + } + +} + +function WaveGround6(){ + + SetCommonData("Rush", true); + + WaveGround5(); + + SetCommonData("Rush", false); + +} + +function Wave1(){ + + int num = FUNC_LERP_ACCEL(W1_fairyNumMin, W1_fairyNumMax, rank/RANK_MAX); + int decel = FUNC_LERP_ACCEL(W1_decelTimeMax, W1_decelTimeMin, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(W1_bulletDelayMax, W1_bulletDelayMin, rank/RANK_MAX); + int spawndel = FUNC_LERP_ACCEL(W1_spawnDelayMax, W1_spawnDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W1_bulletSpdMin, W1_bulletSpdMax, rank/RANK_MAX); + float movespd = baseMoveSpeedH * (1 + MoveSpeedRankMultiplierL*rank); + + task CreateEnemyA(float startX){ + + int enm = _SmallFairy( + 40, decel+5, + startX, -64 + ); + + ObjMove_AddPatternA2(enm, 0, movespd*1.5, 90, -movespd*1.5/decel, 0, 0); + ObjMove_AddPatternA2(enm, decel*1.5, NO_CHANGE, NO_CHANGE, movespd/decel, movespd, 0); + + wait(decel); + + while(!Obj_IsDeleted(enm) && ObjMove_GetY(enm) < STG_HEIGHT * 6/7){ + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), spd, GetAngleToPlayer(enm), KEV_BALL_LAVENDER, 5); + + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 5); + Shoot1; + + wait(del); + + } + + } + + ascent(i in 1..7){ + + CreateEnemyA(i * STG_WIDTH/7); + + if(i != 7){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + ascent(i in 1..7){ + + CreateEnemyA((7-i) * STG_WIDTH/7); + + if(i != 7){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; + +} + +function Wave2(){ + + int num = FUNC_LERP_ACCEL(W2_fairyNumMin, W2_fairyNumMax, rank/RANK_MAX); + int bulletnum = FUNC_LERP_ACCEL(W2_bulletLineNumMin, W2_bulletLineNumMax, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(W2_bulletDelayMax, W2_bulletDelayMin, rank/RANK_MAX); + int spawndel = FUNC_LERP_ACCEL(W2_spawnDelayMax, W2_spawnDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W2_bulletSpdMin, W2_bulletSpdMax, rank/RANK_MAX); + float movespd = baseMoveSpeedM * (1 + MoveSpeedRankMultiplierL*rank); + float range = FUNC_LERP_ACCEL(W2_rangeMin, W2_rangeMax, rank/RANK_MAX); + + task CreateEnemyA(float startX, float startY, float angMove){ + + int enm = _SmallFairy( + 40, del, startX, startY + ); + + ObjMove_AddPatternA1(enm, 0, movespd, angMove); + + while(!Obj_IsDeleted(enm) && ObjMove_GetY(enm) < STG_HEIGHT * 6/7){ + + float ang = rand(-range, range); + + ascent(i in 0..bulletnum){ + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), FUNC_LERP_LINEAR(spd, spd/1.65, i/bulletnum), 90+ang, KEV_LEAF_LAVENDER, 5); + + _BulletRescale(bullet, 0.75, true, 1); + _Delay(bullet, 5); + Shoot2; + + } + + wait(del); + + } + + } + + ascent(i in 1..num){ + + CreateEnemyA(-128, STG_HEIGHT/8 + i * (STG_HEIGHT/16), 0); + CreateEnemyA(STG_WIDTH + 128, STG_HEIGHT/8 + i * (STG_HEIGHT/16), 180); + + if(i != num){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; +} + +function Wave3(){ + + int linenum = FUNC_LERP_LINEAR(W3_bulletLineNumMin, W3_bulletLineNumMax, rank/RANK_MAX); + int dense = FUNC_LERP_LINEAR(W3_bulletDenseMin, W3_bulletDenseMax, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(W3_bulletDelayMax, W3_bulletDelayMin, rank/RANK_MAX); + int zakodel = FUNC_LERP_ACCEL(W3_zakospawnDelayMax, W3_zakospawnDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W3_bulletSpdMin, W3_bulletSpdMax, rank/RANK_MAX); + float movespd = baseMoveSpeed1L * (1 + MoveSpeedRankMultiplierL*rank); + float zakomovespd = baseMoveSpeedVH * (1 + MoveSpeedRankMultiplierL*rank); + float angmovespd =FUNC_LERP_ACCEL(W3_angleMoveSpdMin, W3_angleMoveSpdMax, rank/RANK_MAX); + float startX = [0, STG_WIDTH][GetCommonData("Flying Loops Cleared", 0) % 2]; + float[] moveX = [[180, -angmovespd], [0, angmovespd]][GetCommonData("Flying Loops Cleared", 0) % 2]; + float angStart = rand(0, 360); + int i = 0; + + int enmLarge = _LargeDancer( + 40, 90, + startX, -144 + ); + + async{ + + while(!Obj_IsDeleted(enmLarge)){ + + ObjMove_SetSpeedY(enmLarge, movespd); + ObjMove_SetX(enmLarge, STG_WIDTH/2 + STG_WIDTH/2 * cos(moveX[0])); + + if (ObjMove_GetY(enmLarge) <= FUNC_LERP_LINEAR(144, 48, rank/RANK_MAX)) {ObjEnemy_SetDamageRate(enmLarge, 0, 0);} + else {ObjEnemy_SetDamageRate(enmLarge, 100, 100);} + + moveX[0] += moveX[1]; + + yield; + + } + + } + + while(!Obj_IsDeleted(enmLarge)){ + + int shot = CreateFan(enmLarge, 1, KEV_LEAF_LAVENDER, linenum, + angStart+i*1*360/dense, 0, spd/1.25, spd, + 0.75, + 0, 0, + PATTERN_FAN, false + ); + int shot2 = CreateFan(enmLarge, 1, KEV_LEAF_LAVENDER, linenum, + angStart+(180+angStart)+i*(-1)*360/dense, 0, spd/1.25, spd, + 0.75, + 0, 0, + PATTERN_FAN, false + ); + + Shoot2; + + i++; + wait(del); + + } + + // FUCK YOU HERE'S SOME ZAKO + + task CreateEnemyA(float startX){ + + int enm = _SmallFairy( + 39, zakomovespd*2, + startX, -64 + ); + + ObjMove_AddPatternA1(enm, 0, zakomovespd*1.5, atan2(playerY - (-64), playerX - startX)); + + async{ + while(!Obj_IsDeleted(enm)){ + if (ObjMove_GetY(enm) <= 64) {ObjEnemy_SetDamageRate(enm, 0, 0);} + else {ObjEnemy_SetDamageRate(enm, 400, 400);} + yield; + } + } + + while(!Obj_IsDeleted(enm) && ObjMove_GetY(enm) < STG_HEIGHT * 6/7){ + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), spd*1.2, GetAngleToPlayer(enm), KEV_BALL_LAVENDER, 5); + + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 5); + Shoot1; + + wait(del*10); + + } + + } + + ascent(i in 1..7){ + + CreateEnemyA(i * STG_WIDTH/7); + + if(i != 7){wait(zakodel);} + else{} + + } + + ascent(i in 1..7){ + + CreateEnemyA((7-i) * STG_WIDTH/7); + + if(i != 7){wait(zakodel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; + +} + +function Wave4(){ + + int del = FUNC_LERP_ACCEL(W4_bulletDelayMax, W4_bulletDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W4_bulletSpdMin, W4_bulletSpdMax, rank/RANK_MAX); + int spawndel = FUNC_LERP_ACCEL(W4_spawnDelayMax, W4_spawnDelayMin, rank/RANK_MAX); + int invin = FUNC_LERP_ACCEL(W4_invinTimeMax, W4_invinTimeMin, rank/RANK_MAX); + float movespd = baseMoveSpeedH * (1 + MoveSpeedRankMultiplierVL*rank); + + task CreateEnemyA(float startX){ + + int enm = _Oni( + 41, invin, + startX, -128 + ); + + ObjMove_AddPatternA1(enm, 0, movespd, 90); + + while(!Obj_IsDeleted(enm) && ObjMove_GetY(enm) < STG_HEIGHT * 4/5){ + + if (ObjMove_GetY(enm) <= 128) {ObjEnemy_SetDamageRate(enm, 0, 0);} + else {ObjEnemy_SetDamageRate(enm, 100, 100);} + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), spd, GetAngleToPlayer(enm), KEV_FIRE_PINK, 5); + + _BulletRescale(bullet, 1, true, 1); + _Delay(bullet, 5); + Shoot2; + + wait(del); + + } + + } + + ascent(i in 1..6){ + + CreateEnemyA(1.5*STG_WIDTH/8 + 96); + CreateEnemyA(1.5*STG_WIDTH/8 - 96); + + if(i != 6){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + ascent(i in 1..6){ + + CreateEnemyA(6.5*STG_WIDTH/8 - 96); + CreateEnemyA(6.5*STG_WIDTH/8 + 96); + + if(i != 6){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; + + +} + +// Witch + +function Wave5(){ + + float acceltime = FUNC_LERP_ACCEL(W5_accelTimeMax, W5_accelTimeMin, rank/RANK_MAX); + float bulletwait = FUNC_LERP_ACCEL(W5_bulletWaitTimeMax, W5_bulletWaitTimeMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W5_bulletSpdMin, W5_bulletSpdMax, rank/RANK_MAX); + float angrange = FUNC_LERP_ACCEL(W5_angRangeMin, W5_angRangeMax, rank/RANK_MAX); + float del = FUNC_LERP_ACCEL(W5_bulletDelayMax, W5_bulletDelayMin, rank/RANK_MAX); + float spawndel = FUNC_LERP_ACCEL(W4_spawnDelayMax, W4_spawnDelayMin, rank/RANK_MAX); + float movespd = min(baseMoveSpeedVH * (1 + MoveSpeedRankMultiplierH * rank) * 1.2, 18); + + task CreateEnemyA(float startX){ + + float angMove = atan2(playerY - (-96), playerX - startX); + + int enm = _SmallWitch( + 40, del*20, + startX, -96 + ); + + ObjMove_AddPatternA1(enm, 0, movespd, angMove); + ObjRender_SetAngleZ(enm, angMove); + + while(!Obj_IsDeleted(enm) && ObjMove_GetY(enm) < STG_HEIGHT * 1/2){ + + if (ObjMove_GetY(enm) <= 128) {ObjEnemy_SetDamageRate(enm, 0, 0);} + else {ObjEnemy_SetDamageRate(enm, 100, 100);} + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), 0, angMove+rand(-angrange, angrange), KEV_LEAF_PINK, 5); + + _BulletRescale(bullet, 0.75, true, 1); + _Delay(bullet, 5); + + ObjMove_AddPatternA2(bullet, bulletwait, NO_CHANGE, NO_CHANGE, spd/acceltime, spd, 0); + + wait(del); + + } + + } + + ChargeSFX; + + ascent(i in 1..7){ + + CreateEnemyA(i * STG_WIDTH/7); + + if(i != 7){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + ChargeSFX; + + ascent(i in 1..7){ + + CreateEnemyA((7-i) * STG_WIDTH/7); + + if(i != 7){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; + +} + +function Wave6(){ + + int dense = FUNC_LERP_LINEAR(W6_spiralDenseMin, W6_spiralDenseMax, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(W6_bulletDelayMax, W6_bulletDelayMin, rank/RANK_MAX); + int zakodel = FUNC_LERP_ACCEL(W6_zakospawnDelayMax, W6_zakospawnDelayMin, rank/RANK_MAX); + int waittime = FUNC_LERP_ACCEL(W6_bulletWaitTimeMax, W6_bulletWaitTimeMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W6_bulletSpdMin, W6_bulletSpdMax, rank/RANK_MAX); + float angoff = FUNC_LERP_ACCEL(W6_spiralAngOffsetMax, W6_spiralAngOffsetMin, rank/RANK_MAX); + float movespd = baseMoveSpeedM * (1 + MoveSpeedRankMultiplierL*rank); + float zakomovespd = baseMoveSpeedVH * (1 + MoveSpeedRankMultiplierL*rank); + float space = FUNC_LERP_ACCEL(W6_angRangeMin, W6_angRangeMax, rank/RANK_MAX); + int bulletnum = FUNC_LERP_LINEAR(W6_bulletNumMin, W6_bulletNumMax, rank/RANK_MAX); + float angStart = rand(0, 360); + int i = 0; + + int enmLarge = _LargeWitch( + 40, 90, + playerX, -144 + ); + + async{ + + ObjMove_AddPatternA1(enmLarge, 0, movespd, 90); + + while(!Obj_IsDeleted(enmLarge)){ + + if (ObjMove_GetY(enmLarge) <= FUNC_LERP_LINEAR(144, 48, rank/RANK_MAX)) {ObjEnemy_SetDamageRate(enmLarge, 15, 15);} + else {ObjEnemy_SetDamageRate(enmLarge, 100, 100);} + + yield; + + } + + } + + while(!Obj_IsDeleted(enmLarge) && ObjMove_GetY(enmLarge) <= STG_HEIGHT * 7/8){ + + ascent(i in 0..dense){ + + int bullet = CreateShotA1(ObjMove_GetX(enmLarge) + 64 * cos(angStart + i * 360/dense), ObjMove_GetY(enmLarge) + 64 * sin(angStart + i * 360/dense), 0, angStart + i * 360/dense, KEV_LEAF_PINK, 5); + + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 5); + ObjMove_AddPatternA2(bullet, waittime, NO_CHANGE, NO_CHANGE, spd/waittime, spd, 0); + + } + + angStart += angoff; + + Shoot2; + + wait(del); + + } + + task CreateEnemyA(float startX){ + + float time = waittime/2; + + int enm = _Oni( + 39, waittime*1.5, + startX, -64 + ); + + ObjEnemy_SetDamageRate(enm, 0, 0); + ObjMove_SetDestAtFrame(enm, startX, STG_HEIGHT * 1/8, time, LERP_DECELERATE); + + wait(time-1); + + ObjMove_AddPatternA2(enm, time, NO_CHANGE, 90, zakomovespd/waittime, zakomovespd, 0); + + async{ + while(!Obj_IsDeleted(enm)){ + if (ObjMove_GetY(enm) <= 0) {ObjEnemy_SetDamageRate(enm, 0, 0);} + else {ObjEnemy_SetDamageRate(enm, 200, 200);} + yield; + } + } + + while(!Obj_IsDeleted(enm) && ObjMove_GetY(enm) < STG_HEIGHT * 6/7){ + + CreateFan( + enm, bulletnum, KEV_FIRE_PINK, 1, + GetAngleToPlayer(enm), space, spd*1.25, spd*1.25/1.5, 1, + 0, 0, + PATTERN_FAN, false + ); + + wait(del*999); + + } + + } + + ascent(i in 1..8){ + + CreateEnemyA(i * STG_WIDTH/8); + + } + + wait(waittime/2); + + while(length(enmFly) > 1){yield;} + + return; + +} + +task _EndShake(shaketime, intensity){ + + float baseintensity = intensity; + float shakeno = shaketime; + + ascent(i in 0..shakeno){ + Set2DCameraFocusX(GetStgFrameWidth/2 + rand(-intensity, intensity)); + Set2DCameraFocusY(GetStgFrameHeight/2 + rand(-intensity, intensity)); + intensity = Interpolate_Decelerate(0, baseintensity, 1-i/shakeno); + shaketime--; + yield; + } + + while(shaketime > 0){yield;} + + Set2DCameraFocusX(GetStgFrameWidth/2); + Set2DCameraFocusY(GetStgFrameHeight/2); + yield; +} + +task _ObjShake(objID, shaketime, intensity){ + + float baseX = ObjMove_GetX(objID); + float baseY = ObjMove_GetY(objID); + float baseintensity = intensity; + float shakeno = shaketime; + + ascent(i in 0..shakeno){ + ObjMove_SetPosition(objID, baseX + rand(-intensity, intensity), baseY + rand(-intensity, intensity)/2); + intensity = Interpolate_Decelerate(0, baseintensity, 1-i/shakeno); + shaketime--; + yield; + } + + while(shaketime > 0){yield;} + + ObjMove_SetPosition(objID, baseX, baseY); + + yield; +} + + diff --git a/script/Jam10/GunnerParade_ConstLib.dnh b/script/Jam10/GunnerParade_ConstLib.dnh new file mode 100644 index 0000000..3c17df7 --- /dev/null +++ b/script/Jam10/GunnerParade_ConstLib.dnh @@ -0,0 +1,414 @@ +// Constants + +int difficulty = 0; + +int STAGE_LENGTH = 90; +int BOSS_LENGTH = 30; + +int HP_MAX = 4500; +int PHASE1_LIMIT = 2250; +int PHASE2_LIMIT = 0; +int PHASE3_LIMIT = 0; + +// Rank min/max + +local{ + + alternative(GetCommonData("Difficulty", "Standard")) + + case("Novice"){difficulty = 0;} + case("Standard"){difficulty = 1;} + case("Extra"){difficulty = 2;} + others{difficulty = 0;} + +} + + +float RANK_MIN = [1, 1, 9][difficulty]; +float RANK_MAX = 9; // Since Novice locks Rank to a lower level, this distinction is necessary +float RANK_MAX_TRUE = [6, 9, 9][difficulty]; // Can be changed + +SetCommonData("MinRank", RANK_MIN); +SetCommonData("MaxRank", RANK_MAX_TRUE); + +// Enemy parameters + +int smallEnemyHitbox = 32; +int medEnemyHitbox = 64; +int largeEnemyHitbox = 100; +int spiritHitbox = 48; + +float smallEnemyHP = 45; +float mediumEnemyHP = 80; +float largeEnemyHP = 120; +float largeEnemyAltHP = 150; +float popcornHP = 25; + +float smallEnemyScale = 1; +float largeEnemyScale = 1; +float popcornScale = 1; + +// Enemy rects + +int[] smallfairyRect = [0, 128, 128, 256]; +int[] spiritRect = [0, 0, 128, 128]; +int[] mushroomfairyRect = [0, 256, 192, 448]; +int[] yukionnaRect = [0, 448, 192, 640]; +int[] bossRect = [192, 448, 384, 704]; + +// Universal + +// MOVEMENT SPEED RELATED + + // Very low speed (ground, large enemies) + float baseMoveSpeedVL = 5.5; + + // Low speed (ground, large enemies) + float baseMoveSpeed1L= 7; + + // Medium speed + float baseMoveSpeedM = 8; + + // High speed + float baseMoveSpeedH = 10; + + // Very high speed + float baseMoveSpeedVH = 11.5; + + // Speed multiplier per rank - speed increases by 0.02/0.03x per rank increase up to a max of 0.18/0.27x + + float MoveSpeedRankMultiplierVL = 0.015; + float MoveSpeedRankMultiplierL = 0.025; + float MoveSpeedRankMultiplierH = 0.035; + float MoveSpeedRankMultiplierVH = 0.05; + +// ITEM RELATED + + float smallFlyingEnm_itemPointMin = 8; + float smallFlyingEnm_itemPointMax = 12; + + float medFlyingEnm_itemPointMin = 12; + float medFlyingEnm_itemPointMax = 18; + + float largeFlyingEnm_itemPointMin = 20; + float largeFlyingEnm_itemPointMax = 30; + + float verylargeFlyingEnm_itemPointMin = 35; + float verylargeFlyingEnm_itemPointMax = 45; + + // 1 ammo item = 2 ammo + + float smallGroundEnm_itemAmmoMin = 2; + float smallGroundEnm_itemAmmoMax = 4; + + float medGroundEnm_itemAmmoMin = 4; + float medGroundEnm_itemAmmoMax = 6; + + float largeGroundEnm_itemAmmoMin = 12; + float largeGroundEnm_itemAmmoMax = 18; + + float verylargeGroundEnm_itemAmmoMin = 40; + float verylargeGroundEnm_itemAmmoMax = 60; + + float smallEnm_itemChainMin = 6; + float smallEnm_itemChainMax = 12; + + float mediumEnm_itemChainMin = 9; + float mediumEnm_itemChainMax = 16; + + float largeEnm_itemChainMin = 12; + float largeEnm_itemChainMax = 20; + + float itemMultiplier = 0.03; // For point items only + +// INVINCIBILITY TIME + + // Short, medium, long + int[] invinTimeArr = [20, 40, 60]; + int[] invinTimeDecrease = [1, 2, 3]; // Per rank increase + +// Wave 1 + + // Graphic: fairy + + // Uses high speed, fires aimed bullets + + int W1_spawnDelayMin = 4; + int W1_spawnDelayMax = 8; + + int W1_fairyNumMin = 5; + int W1_fairyNumMax = 8; + + int W1_decelTimeMin = 20; + int W1_decelTimeMax = 30; + + int W1_bulletDelayMin = 40; + int W1_bulletDelayMax = 50; + + float W1_bulletSpdMin = 9; + float W1_bulletSpdMax = 12; + +// Wave 2 + + // Graphic: spirit + + // Sin-wave movement, fires aimed small-fire fans + + int W2_fairyNumMin = 3; + int W2_fairyNumMax = 5; + + int W2_bulletDelayMin = 65; + int W2_bulletDelayMax = 90; + + float W2_bulletSpdMin = 10; + float W2_bulletSpdMax = 13; + + float W2_rangeMin = 2; + float W2_rangeMax = 3.25; + + int W2_bulletfanNumMin = 3; + int W2_bulletfanNumMax = 5; + + int W2_spawnDelayMin = 10; + int W2_spawnDelayMax = 15; + +// Wave 3: Mushroom fairy, fires large fireballs + + int W3_spawnDelayMin = 15; + int W3_spawnDelayMax = 30; + + int W3_fairyNumMin = 3; + int W3_fairyNumMax = 9; + + float W3_rangeMin = 1; + float W3_rangeMax = 2.5; + + int W3_bulletfanNumMin = 1; + int W3_bulletfanNumMax = 1; + + int W3_bulletDelayMin = 15; + int W3_bulletDelayMax = 20; + + float W3_bulletSpdMin = 11; + float W3_bulletSpdMax = 13; + +// Wave 4: Mushroom fairy, fires small fireball lines + + int W4_spawnDelayMin = 18; + int W4_spawnDelayMax = 35; + + int W4_fairyNumMin = 2; + int W4_fairyNumMax = 5; + + int W4_bulletNumMin = 3; + int W4_bulletNumMax = 5; + + int W4_bulletDelayMin = 2; + int W4_bulletDelayMax = 4; + + int W4_stopTimeMin = 20; + int W4_stopTimeMax = 30; + + float W4_bulletSpdMin = 10; + float W4_bulletSpdMax = 12.25; + +// Wave 5: Clumped small fairy lines come from both sides to attack you. + + int W5_spawnDelayMin = 20; + int W5_spawnDelayMax = 40; + + int W5_fairyNumMin = 3; + int W5_fairyNumMax = 6; + + // Angles + + int W5_moveTimeMin = 40; + int W5_moveTimeMax = 50; + + float W5_bulletSpdMin = 11; + float W5_bulletSpdMax = 13; + +// Wave 6: Alt mushroom fairies (2 OR 3) spawns sparse rings (counts as ground) + + int WG1_ringDenseMin = 10; + int WG1_ringDenseMax = 14; + + float WG1_bulletSpdMin = 8; + float WG1_bulletSpdMax = 11; + + int WG1_bulletDelayMin = 30; + int WG1_bulletDelayMax = 45; + +// Wave 7: Yukionna with spiral (counts as ground) + + int WG2_spiralDenseMin = 6; + int WG2_spiralDenseMax = 9; + + int WG2_spiralNumMin = 3; + int WG2_spiralNumMax = 5; + + float WG2_spiralSpdMin = 7.5; + float WG2_spiralSpdMax = 9.5; + + int WG2_spiralDelayMax = 40; + int WG2_spiralDelayMin = 25; + +/* +// Wave Ground 1 + + int[] sign1Rect = [1024, 512, 1280, 768]; + int[] platformRect = [1536, 256, 2304, 768]; + + int WG1_invinTimeMin = 15; + int WG1_invinTimeMax = 25; + +// Wave Ground 2 + + int[] cannonRect = [2048, 768, 2304, 1024]; + int[] bushRect = [512, 1024, 1280, 1536]; + + int WG2_bulletNumMin = 3; + int WG2_bulletNumMax = 5; + + float WG2_angRangeMin = 1.4; + float WG2_angRangeMax = 2; + + float WG2_bulletSpdMin = 9; + float WG2_bulletSpdMax = 11; + + int WG2_bulletDelayMin = 30; + int WG2_bulletDelayMax = 40; + + int WG2_invinTimeMin = 45; + int WG2_invinTimeMax = 60; + +// Wave Ground 1A + + // Graphic: fairy + + // Uses high speed + + int WG1A_bulletNumMin = 1; + int WG1A_bulletNumMax = 3; + + int WG1A_bulletDelayMin = 45; + int WG1A_bulletDelayMax = 60; + + float WG1A_bulletSpdMin = 12; + float WG1A_bulletSpdMax = 15; + + int[] sign2Rect = [1280, 512, 1536, 768]; + + int WG1A_invinTimeMin = 25; + int WG1A_invinTimeMax = 40; + +// Wave Ground 3 (Rybb) -> orange line spirals + + int WG3_spiralDenseMin = 5; + int WG3_spiralDenseMax = 8; + + int WG3_spiralNumMin = 3; + int WG3_spiralNumMax = 6; + + float WG3_spiralSpdMin = 7.5; + float WG3_spiralSpdMax = 9.5; + + int WG3_spiralDelayMax = 40; + int WG3_spiralDelayMin = 30; + + int[] rybbRect = [1280, 1024, 1792, 1536]; + +// Wave Ground 4 (ITS THE FUCKING BUSSY FAIRIES) +// Number of fairies affected by RANK and KILL SPEED + + int[] bush2Rect = [512, 1536, 1280, 2048]; + int[] bush2ARect = [256, 1536, 512, 1792]; + + int WG4_enmNumMin = 4; + int WG4_enmNumMax = 6; + + int WG4_bulletDelayMin = 45; + int WG4_bulletDelayMax = 60; + + float WG4_bulletSpdMin = 11; + float WG4_bulletSpdMax = 14; + + int WG4_invinTimeMin = 100; + int WG4_invinTimeMax = 120; + +// Wave Ground 5 (Decker) -> Line bullets. + + int WG5_bulletNumMin = 4; + int WG5_bulletNumMax = 6; + + int WG5_bulletDelayMin = 12; + int WG5_bulletDelayMax = 15; + + float WG5_bulletSpdMin = 7; + float WG5_bulletSpdMax = 9; + + int[] deckerRect = [1792, 1024, 1792+512, 1536]; + +// Wave Ground 6 -> Your ass is our base +*/ + +task UpdateDrops(){ + + // According to rank + + while(true){ + + smallFlyingEnm_itemPointMax = FUNC_LERP_LINEAR(12, 18, rank/RANK_MAX); + medFlyingEnm_itemPointMax = FUNC_LERP_LINEAR(16, 24, rank/RANK_MAX); + largeFlyingEnm_itemPointMax = FUNC_LERP_LINEAR(30, 40, rank/RANK_MAX); + verylargeFlyingEnm_itemPointMax = FUNC_LERP_LINEAR(45, 60, rank/RANK_MAX); + + smallGroundEnm_itemAmmoMax = FUNC_LERP_LINEAR(4, 6, rank/RANK_MAX); + medGroundEnm_itemAmmoMax = FUNC_LERP_LINEAR(6, 8, rank/RANK_MAX); + largeGroundEnm_itemAmmoMax = FUNC_LERP_LINEAR(18, 25, rank/RANK_MAX); + verylargeGroundEnm_itemAmmoMax = FUNC_LERP_LINEAR(60, 75, rank/RANK_MAX); + + smallEnm_itemChainMax = FUNC_LERP_LINEAR(12, 16, rank/RANK_MAX); + mediumEnm_itemChainMax = FUNC_LERP_LINEAR(16, 20, rank/RANK_MAX); + largeEnm_itemChainMax = FUNC_LERP_LINEAR(20, 24, rank/RANK_MAX); + + wait(5); + + } +} + +/* + +Reference: + + task SpawnSpiral(float angStart, int spinDir){ + + async{ + ascent(i in -1..linespiralNum[diff]){ + + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){break;} + + int shot = CreateFan(bossObj, 1, KEV_LEAF_ORANGE, linespiralLineCount[diff], + angStart+i*spinDir*linespiralAngOffset[diff], 0, linespiralSpd2[diff], linespiralSpd1[diff], + 0.6, + 0, 0, + PATTERN_FAN, false + ); + int shot2 = CreateFan(bossObj, 1, KEV_LEAF_ORANGE, linespiralLineCount[diff], + angStart+(180+angStart)-i*spinDir*linespiralAngOffset[diff], 0, linespiralSpd2[diff], linespiralSpd1[diff], 0.6, + 0, 0, + PATTERN_FAN, false + ); + + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){Obj_Delete(shot); Obj_Delete(shot2);} + + else{Shoot1;} + + wait([4, 4, 3, 3][diff]); + + } + } + + } + +*/ \ No newline at end of file diff --git a/script/Jam10/GunnerParade_EnmLib.dnh b/script/Jam10/GunnerParade_EnmLib.dnh new file mode 100644 index 0000000..e96cb82 --- /dev/null +++ b/script/Jam10/GunnerParade_EnmLib.dnh @@ -0,0 +1,1618 @@ +let texEnm = "script/Jam10/resourceLib/Jam10.png"; +#include "script/Jam10/GunnerParade_ConstLib.dnh" + +float deadZone = STG_WIDTH - 32; +float deadZoneB = STG_HEIGHT - 16; + +LoadTextureEx(texEnm, true, true); + +task _RenderBossFight(int enemy){ + + int aniidle = 0; + + //LoadTextureEx(tex, true, true); + + ObjPrim_SetTexture(enemy, texEnm); + ObjSprite2D_SetSourceRect(enemy, bossRect[0], bossRect[1], bossRect[2], bossRect[3]); + ObjSprite2D_SetDestCenter(enemy); + ObjRender_SetScaleXYZ(enemy, 1); + + /* + int nameText = CreateTextObject( + GetStgFrameWidth()*0.3, 200, 25, + "REMILIA SCARLET", "Origami Mommy", + 0xFF5A5A, 0xFFFFFF, + 0x791D1D, 3, + 1 + ); + + ObjRender_SetAngleZ(nameText, -90); + ObjText_SetFontBold(nameText, true); + */ + + //_BossMarker(enemy, tex, 512, 0, 768, 256, 0.45, 30); + +} + +function CreateUmbrellaEnemy( + int renderPriority, int[] rect, + float enmX, enmY, scale, hitbox, + int invinTime, int killTime, int enmHealth, int itemDropPoint, int itemDropChain + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + scale, scale, + enmHealth, hitbox, 0, + texEnm, + rect[0], rect[1], rect[2], rect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + async{ + while(!Obj_IsDeleted(enm)){ + ObjRender_SetAngleZ(enm, ObjRender_GetAngleZ(enm)+1.5); + yield; + } + } + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + + wait(invinTime); + + ObjEnemy_SetAutoDelete(enm, true); + + } + + _EnemyItemDrop( + enm, true, + itemDropPoint, itemDropChain, + itemDropPoint*2+(GetCommonDataPtr(RANK_PTR, 1)-1)*2, itemDropChain*2+(GetCommonDataPtr(RANK_PTR, 1)-1)*2, + killTime, hitbox*2.5 + ); + + return enm; + +} + +function CreateFan (int parent, int way, int graphic, int stack, + float ang, float angspace, float spd1, float spd2, float scaleBullet, + int type, bool reflect){ + + int objPattern = ObjPatternShot_Create(); + + ObjPatternShot_SetParentObject(objPattern, parent); + + //if(ObjEnemyBossScene_GetInfo(GetEnemyBossSceneObjectID(), INFO_CURRENT_LIFE) == 0){Obj_Delete(objPattern); return;} + + ObjPatternShot_SetPatternType(objPattern, type); // PATTERN_FAN or PATTERN_FAN_AIMED + ObjPatternShot_SetShotType(objPattern, OBJ_SHOT); + ObjPatternShot_SetInitialBlendMode(objPattern, BLEND_ALPHA); + + ObjPatternShot_SetShotCount(objPattern, way, stack); + ObjPatternShot_SetSpeed(objPattern, spd1, spd2); + ObjPatternShot_SetAngle(objPattern, ang, angspace); + + ObjPatternShot_SetBasePointOffset(objPattern, 0, 0); + //ObjPatternShot_SetDelay(objPattern, 15); + ObjPatternShot_SetGraphic(objPattern, graphic); + + //Shoot2; + let arrayPattern = ObjPatternShot_FireReturn(objPattern); + + ascent(i in -1..length(arrayPattern)-1){ + _BulletRescale(arrayPattern[i], scaleBullet, true, 0.25); + _Delay(arrayPattern[i], 5); + //Obj_SetRenderPriorityI(arrayPattern[i], 51); + } + + async{ + wait(300); + Obj_Delete(objPattern); + return; + } + + return objPattern; + +} + +// Overload + +function CreateFan (int parent, int way, int graphic, int stack, + float ang, float angspace, float spd1, float spd2, float scaleBullet, + float xOffset, float yOffset, + int type, bool reflect){ + + int objPattern = ObjPatternShot_Create(); + + ObjPatternShot_SetParentObject(objPattern, parent); + + //if(ObjEnemyBossScene_GetInfo(GetEnemyBossSceneObjectID(), INFO_CURRENT_LIFE) == 0){Obj_Delete(objPattern); return;} + + ObjPatternShot_SetPatternType(objPattern, type); // PATTERN_FAN or PATTERN_FAN_AIMED + ObjPatternShot_SetShotType(objPattern, OBJ_SHOT); + ObjPatternShot_SetInitialBlendMode(objPattern, BLEND_ALPHA); + + ObjPatternShot_SetShotCount(objPattern, way, stack); + ObjPatternShot_SetSpeed(objPattern, spd1, spd2); + ObjPatternShot_SetAngle(objPattern, ang, angspace); + + ObjPatternShot_SetBasePointOffset(objPattern, xOffset, yOffset); + //ObjPatternShot_SetDelay(objPattern, 15); + ObjPatternShot_SetGraphic(objPattern, graphic); + + //Shoot2; + let arrayPattern = ObjPatternShot_FireReturn(objPattern); + + ascent(i in -1..length(arrayPattern)-1){ + _BulletRescale(arrayPattern[i], scaleBullet, true, 0.25); + _Delay(arrayPattern[i], 5); + //Obj_SetRenderPriorityI(arrayPattern[i], 51); + } + + async{ + wait(300); + Obj_Delete(objPattern); + return; + } + + return objPattern; + +} + +// Enemy Type 1: Fairy (Wave 1, 2) + +function _SmallFairy( + int renderPriority, invinTime, + float enmX, float enmY + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + smallEnemyScale, smallEnemyScale, + popcornHP, smallEnemyHitbox, 0, + texEnm, + smallfairyRect[0], smallfairyRect[1], smallfairyRect[2], smallfairyRect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + int frame = 0; + + async{ + + while(!Obj_IsDeleted(enm)){ + + ObjSprite2D_SetSourceRect(enm, smallfairyRect[0]+128*floor(frame/6), smallfairyRect[1], smallfairyRect[2]+128*floor(frame/6), smallfairyRect[3]); + + frame++; + + if (frame >= (2*6-1)){frame = 0;} + + yield; + + } + + } + + async{ + + while(!Obj_IsDeleted(enm)){ + + if(ObjMove_GetX(enm) > deadZone){ObjEnemy_SetDamageRate(enm, 0, 0);} + else{ObjEnemy_SetDamageRate(enm, 100, 100);} + + yield; + + } + + } + + _EnemyItemDrop( + enm, true, + smallFlyingEnm_itemPointMin, smallEnm_itemChainMin, + smallFlyingEnm_itemPointMax, smallEnm_itemChainMax, + invinTime*4, smallEnemyHitbox*2 + ); + + return enm; + +} + +function _MushroomFairy( + int renderPriority, invinTime, + float enmX, float enmY + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + smallEnemyScale, smallEnemyScale, + mediumEnemyHP, medEnemyHitbox, 0, + texEnm, + mushroomfairyRect[0], mushroomfairyRect[1], mushroomfairyRect[2], mushroomfairyRect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + int frame = 0; + + async{ + + while(!Obj_IsDeleted(enm)){ + + ObjSprite2D_SetSourceRect(enm, mushroomfairyRect[0]+192*floor(frame/6), mushroomfairyRect[1], mushroomfairyRect[2]+192*floor(frame/6), mushroomfairyRect[3]); + + frame++; + + if (frame >= (2*6-1)){frame = 0;} + + yield; + + } + + } + + async{ + + while(!Obj_IsDeleted(enm)){ + + if(ObjMove_GetX(enm) > deadZone){ObjEnemy_SetDamageRate(enm, 0, 0);} + else{ObjEnemy_SetDamageRate(enm, 100, 100);} + + yield; + + } + + } + + _EnemyItemDrop( + enm, true, + smallFlyingEnm_itemPointMin, smallEnm_itemChainMin, + smallFlyingEnm_itemPointMax, smallEnm_itemChainMax, + invinTime*5, smallEnemyHitbox*2 + ); + + return enm; +} + +function _MushroomFairyAlt( + int renderPriority, invinTime, + float enmX, float enmY + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + smallEnemyScale, smallEnemyScale, + mediumEnemyHP, medEnemyHitbox, 0, + texEnm, + mushroomfairyRect[0]+384, mushroomfairyRect[1], mushroomfairyRect[2]+384, mushroomfairyRect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + int frame = 0; + + async{ + + while(!Obj_IsDeleted(enm)){ + + ObjSprite2D_SetSourceRect(enm, mushroomfairyRect[0]+192*floor(frame/6)+384, mushroomfairyRect[1], mushroomfairyRect[2]+192*floor(frame/6)+384, mushroomfairyRect[3]); + + frame++; + + if (frame >= (2*6-1)){frame = 0;} + + yield; + + } + + } + + async{ + + while(!Obj_IsDeleted(enm)){ + + if(ObjMove_GetX(enm) > deadZone){ObjEnemy_SetDamageRate(enm, 0, 0);} + else{ObjEnemy_SetDamageRate(enm, 100, 100);} + + yield; + + } + + } + + _EnemyItemDrop( + enm, true, + medFlyingEnm_itemPointMin, smallEnm_itemChainMin, + medFlyingEnm_itemPointMax, smallEnm_itemChainMax, + invinTime*5, smallEnemyHitbox*2 + ); + + return enm; +} + +function _YukiOnna( + int renderPriority, invinTime, + float enmX, float enmY + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + smallEnemyScale, smallEnemyScale, + largeEnemyHP, largeEnemyHitbox, 0, + texEnm, + yukionnaRect[0], yukionnaRect[1], yukionnaRect[2], yukionnaRect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + async{ + + while(!Obj_IsDeleted(enm)){ + + if(ObjMove_GetX(enm) > deadZone){ObjEnemy_SetDamageRate(enm, 0, 0);} + else{ObjEnemy_SetDamageRate(enm, 100, 100);} + + yield; + + } + + } + + _EnemyItemDrop( + enm, true, + largeFlyingEnm_itemPointMin, smallEnm_itemChainMin, + largeFlyingEnm_itemPointMax, smallEnm_itemChainMax, + invinTime*6, largeEnemyHitbox*2 + ); + + return enm; +} + +// Enemy Type 2: Oni/Bird (Wave 4) + +function _Spirit( + int renderPriority, invinTime, + float enmX, float enmY + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + smallEnemyScale, smallEnemyScale, + smallEnemyHP, spiritHitbox, 0, + texEnm, + spiritRect[0], spiritRect[1], spiritRect[2], spiritRect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + int frame = 0; + + async{ + + while(!Obj_IsDeleted(enm)){ + + ObjSprite2D_SetSourceRect(enm, spiritRect[0]+128*floor(frame/6), spiritRect[1], spiritRect[2]+128*floor(frame/6), spiritRect[3]); + + frame++; + + if (frame >= (2*6-1)){frame = 0;} + + yield; + + } + + } + + async{ + + while(!Obj_IsDeleted(enm)){ + + if(ObjMove_GetX(enm) > deadZone){ObjEnemy_SetDamageRate(enm, 0, 0);} + else{ObjEnemy_SetDamageRate(enm, 100, 100);} + + yield; + + } + + } + + _EnemyItemDrop( + enm, true, + smallFlyingEnm_itemPointMin, smallEnm_itemChainMin, + smallFlyingEnm_itemPointMax, smallEnm_itemChainMax, + invinTime*4, smallEnemyHitbox*2 + ); + + return enm; + +} + +// Enemy Type 3: Witch/Dancer (Wave 5) + +/* +function _SmallWitch( + int renderPriority, invinTime, + float enmX, float enmY + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + smallEnemyScale, smallEnemyScale*1.5, + smallEnemyHP, smallEnemyHitbox, 0, + texEnm, + smallwitchRect[0], smallwitchRect[1], smallwitchRect[2], smallwitchRect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + wait(5); + ObjEnemy_SetAutoDelete(enm, true); + wait(invinTime-5); + ObjEnemy_SetDamageRate(enm, 100, 100); + + } + + _EnemyItemDrop( + enm, true, + smallFlyingEnm_itemPointMin, smallEnm_itemChainMin, + smallFlyingEnm_itemPointMax, smallEnm_itemChainMax, + invinTime*2, smallEnemyHitbox*2 + ); + + return enm; + +} + +function _LargeWitch( + int renderPriority, invinTime, + float enmX, float enmY + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + largeEnemyScale, largeEnemyScale, + largeEnemyHP, largeEnemyHitbox, 0, + texEnm, + largewitchRect[0], largewitchRect[1], largewitchRect[2], largewitchRect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + wait(5); + ObjEnemy_SetAutoDelete(enm, true); + wait(invinTime-5); + ObjEnemy_SetDamageRate(enm, 100, 100); + + } + + _EnemyItemDrop( + enm, true, + largeFlyingEnm_itemPointMin, largeEnm_itemChainMin, + largeFlyingEnm_itemPointMax, largeEnm_itemChainMax, + invinTime*2, largeEnemyHitbox*2 + ); + + return enm; + +} + +function _LargeDancer( + int renderPriority, invinTime, + float enmX, float enmY + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + largeEnemyScale, largeEnemyScale, + largeEnemyHP, largeEnemyHitbox, 0, + texEnm, + largedancerRect[0], largedancerRect[1], largedancerRect[2], largedancerRect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + wait(5); + ObjEnemy_SetAutoDelete(enm, true); + wait(invinTime-5); + ObjEnemy_SetDamageRate(enm, 100, 100); + + } + + _EnemyItemDrop( + enm, true, + largeFlyingEnm_itemPointMin, largeEnm_itemChainMin, + largeFlyingEnm_itemPointMax, largeEnm_itemChainMax, + invinTime*2, largeEnemyHitbox*2 + ); + + return enm; + +} + +function _Fish( + int renderPriority, invinTime, + float enmX, float enmY + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + smallEnemyScale, smallEnemyScale, + smallEnemyHP, smallEnemyHitbox, 0, + texEnm, + 1280, 768, 1280+256, 768+256); + + Obj_SetRenderPriorityI(enm, renderPriority); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + wait(5); + ObjEnemy_SetAutoDelete(enm, true); + wait(invinTime-5); + ObjEnemy_SetDamageRate(enm, 100, 100); + + } + + _EnemyItemDrop( + enm, true, + smallFlyingEnm_itemPointMin, smallEnm_itemChainMin, + smallFlyingEnm_itemPointMax, smallEnm_itemChainMax, + invinTime*2, smallEnemyHitbox*2 + ); + + return enm; + +} + +// Ground Enemy 1 + +task _CreateSign1( + int renderPriority, invinTime, + float enmX, float enmY, float movespd + ){ + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + popcornScale, popcornScale, + popcornHP, popcornHitbox, 0, + texEnm, + sign1Rect[0], sign1Rect[1], sign1Rect[2], sign1Rect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + ObjMove_SetSpeed(enm, movespd); + ObjMove_SetAngle(enm, 90); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + + wait(invinTime); + + ObjEnemy_SetAutoDelete(enm, true); + + } + + _EnemyItemDrop( + enm, false, + 1, smallEnm_itemChainMin, smallGroundEnm_itemAmmoMin, + smallFlyingEnm_itemPointMax/2, smallEnm_itemChainMax, smallGroundEnm_itemAmmoMax, + invinTime*2, popcornHitbox*2 + ); + +} + +function _CreateSign1A( + int renderPriority, invinTime, + float enmX, float enmY, float movespd + ){ + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + popcornScale, popcornScale, + popcornHP, popcornHitbox, 0, + texEnm, + sign2Rect[0], sign2Rect[1], sign2Rect[2], sign2Rect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + ObjMove_SetSpeed(enm, movespd); + ObjMove_SetAngle(enm, 90); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + + wait(invinTime); + + ObjEnemy_SetAutoDelete(enm, true); + + } + + _EnemyItemDrop( + enm, false, + smallFlyingEnm_itemPointMin, smallEnm_itemChainMin, smallGroundEnm_itemAmmoMin, + smallFlyingEnm_itemPointMax, smallEnm_itemChainMax, smallGroundEnm_itemAmmoMax, + invinTime*2, popcornHitbox*2 + ); + + return enm; +} + +// Ground Enemy 2 + +function _CreateCannon1( + int renderPriority, invinTime, + float enmX, float enmY, float movespd + ){ + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + 1, 1, + mediumEnemyHP, largeEnemyHitbox, 0, + texEnm, + cannonRect[0], cannonRect[1], cannonRect[2], cannonRect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + ObjMove_SetSpeed(enm, movespd); + ObjMove_SetAngle(enm, 90); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + + wait(invinTime); + + ObjEnemy_SetAutoDelete(enm, true); + + } + + _EnemyItemDrop( + enm, false, + smallFlyingEnm_itemPointMin, mediumEnm_itemChainMin, medGroundEnm_itemAmmoMin, + smallFlyingEnm_itemPointMax, mediumEnm_itemChainMax, medGroundEnm_itemAmmoMax, + invinTime*3, largeEnemyHitbox*2 + ); + + return enm; + +} + +// 6 signs + +task _SignPlatform1( + int renderPriority, invinTime, + float platformX, float platformY, float movespd + ){ + + int enmPad = _CreateEnemy( + false, + platformX, platformY, platformX, platformY, 5, + 0.6, 0.6, + 999, 0, 0, + texEnm, + platformRect[0], platformRect[1], platformRect[2], platformRect[3]); + + float offsetX = 128, offsetY = 64; + + Obj_SetRenderPriorityI(enmPad, renderPriority); + + ObjMove_SetSpeed(enmPad, movespd); + ObjMove_SetAngle(enmPad, 90); + + ObjEnemy_SetDamageRate(enmPad, 0, 0); + + async{ + + ascent(i in 0..3){ + + _CreateSign1( + renderPriority+1, invinTime, + platformX-128+(offsetX*2)-(offsetX*i), platformY-offsetY-offsetY*0.5, movespd + ); + + } + + ascent(i in 0..3){ + + _CreateSign1( + renderPriority+2, invinTime, + platformX-128+(offsetX*2)-(offsetX*i), platformY+offsetY-offsetY*0.5, movespd + ); + + } + + } + + wait(invinTime); + + ObjEnemy_SetAutoDelete(enmPad, true); + +} + +// 3 signs per platform, straight line + +function _SignPlatform1A( + int renderPriority, invinTime, + float platformX, float platformY, float movespd + ){ + + int[] signs = []; + + int enmPad = _CreateEnemy( + false, + platformX, platformY, platformX, platformY, 5, + 0.8, 0.8, + 999, 0, 0, + texEnm, + platformRect[0], platformRect[1], platformRect[2], platformRect[3]); + + float offsetX = 128, offsetY = 64; + + Obj_SetRenderPriorityI(enmPad, renderPriority); + + ObjMove_SetSpeed(enmPad, movespd); + ObjMove_SetAngle(enmPad, 90); + + ObjEnemy_SetDamageRate(enmPad, 0, 0); + + async{ + + ascent(i in 0..3){ + + int sign = _CreateSign1A( + renderPriority+1, invinTime, + platformX-128+(offsetX*2)-(offsetX*i), platformY-offsetY-offsetY*0.5, movespd + ); + + signs ~= [sign]; + + } + + } + + async{ + wait(invinTime); + + ObjEnemy_SetAutoDelete(enmPad, true); + } + + return signs; + +} + +// A Bussy + +function _CreateCannonBush( + int renderPriority, invinTime, + float platformX, float platformY, float movespd + ){ + + int[] signs = []; + + int enmPad = _CreateEnemy( + false, + platformX, platformY, platformX, platformY, 5, + 1.2, 1.2, + 999, 0, 0, + texEnm, + bushRect[0], bushRect[1], bushRect[2], bushRect[3]); + + float offsetX = 280, offsetY = 64; + + Obj_SetRenderPriorityI(enmPad, renderPriority); + + ObjMove_SetSpeed(enmPad, movespd); + ObjMove_SetAngle(enmPad, 90); + + ObjEnemy_SetDamageRate(enmPad, 0, 0); + + async{ + + ascent(i in -1..1){ + + int enm = _CreateCannon1( + renderPriority+1, invinTime, + platformX-[135, -135][i], platformY, movespd + ); + + signs ~= [enm]; + + } + + } + + async{ + + wait(invinTime); + + ObjEnemy_SetAutoDelete(enmPad, true); + + } + + return signs; + +} + +// A Bussy for Only The BIGGEST BITCHES IN TOWN (additional zako not included) + +function _CreateDangerBush( + int renderPriority, invinTime, + float platformX, float platformY, float movespd + ){ + + int enmPad = _CreateEnemy( + true, + platformX, platformY, platformX, platformY, 5, + 1, 1, + largeEnemyHP, largeEnemyHitbox*2.5, 0, + texEnm, + bush2Rect[0], bush2Rect[1], bush2Rect[2], bush2Rect[3]); + + float offsetX = 280, offsetY = 64; + float x = 0, y = 0; + + Obj_SetRenderPriorityI(enmPad, renderPriority); + + ObjMove_SetSpeed(enmPad, movespd); + ObjMove_SetAngle(enmPad, 90); + + ObjEnemy_SetDamageRate(enmPad, 0, 0); + + // Sigil + async{ + + if(GetCommonData("Ground Loops Cleared", 0) % 2 == 0 && GetCommonData("Ground Loops Cleared", 0) != 0 && GetCommonData("Difficulty", "Standard") != "Extra"){ + + int sigil = _Create2DImage(texEnm, [0, 1024, 512, 1536]); + ObjRender_SetAlpha(sigil, 180); + Obj_SetRenderPriorityI(sigil, Obj_GetRenderPriorityI(enmPad)+1); + + while(ObjEnemy_GetInfo(enmPad, INFO_LIFE) > 0){ + ObjRender_SetPosition(sigil, ObjMove_GetX(enmPad), ObjMove_GetY(enmPad), 1); + ObjRender_SetAngleZ(sigil, ObjRender_GetAngleZ(sigil)+1.5); + yield; + } + + Obj_Delete(sigil); + + } + + } + + // Drops + async{ + + while(!Obj_IsDeleted(enmPad)){ + + x = ObjMove_GetX(enmPad); + y = ObjMove_GetY(enmPad); + + if (y < STG_HEIGHT/8) {ObjEnemy_SetDamageRate(enmPad, 0, 0);} + else {ObjEnemy_SetDamageRate(enmPad, 100, 100);} + + yield; + } + + if( + (-128 < x && x < STG_WIDTH+128) + && + (y < STG_HEIGHT+128) + ) + { + DeleteShotInCircle(TYPE_SHOT, TYPE_ITEM, x, y, 256); + ObjSound_Play(bossBoom); + if(GetCommonData("Ground Loops Cleared", 0) % 2 == 0 && GetCommonData("Ground Loops Cleared", 0) != 0 && GetCommonData("Difficulty", "Standard") != "Extra"){CreateExtendItem(EXTEND_SPELL, x, y);} + TExplosionA(x, y, 10, 0.5); + } + + } + + // Shake + async{ + + while(!Obj_IsDeleted(enmPad)){ + float value = rand(-4, 4); + ObjMove_SetPosition(enmPad, x + value, y + value); + yield; + } + + } + + async{ + + wait(invinTime); + + ObjEnemy_SetAutoDelete(enmPad, true); + ObjEnemy_SetDamageRate(enmPad, 100, 100); + + } + + _EnemyItemDrop( + enmPad, false, + medFlyingEnm_itemPointMin, mediumEnm_itemChainMin, verylargeGroundEnm_itemAmmoMin, + medFlyingEnm_itemPointMax, mediumEnm_itemChainMax, verylargeGroundEnm_itemAmmoMax, + invinTime*3, largeEnemyHitbox*3.5 + ); + + return enmPad; + +} + +function _CreateBushRemnant( + int renderPriority, invinTime, + float enmX, float enmY + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + smallEnemyScale, smallEnemyScale, + smallEnemyHP, smallEnemyHitbox, 0, + texEnm, + bush2ARect[0], bush2ARect[1], bush2ARect[2], bush2ARect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + wait(5); + ObjEnemy_SetAutoDelete(enm, true); + wait(invinTime-5); + ObjEnemy_SetDamageRate(enm, 100, 100); + + } + + _EnemyItemDrop( + enm, true, + smallFlyingEnm_itemPointMin/2, smallEnm_itemChainMin/2, smallGroundEnm_itemAmmoMin, + smallFlyingEnm_itemPointMax/2, smallEnm_itemChainMax/2, smallGroundEnm_itemAmmoMax, + invinTime*2, smallEnemyHitbox*2 + ); + + return enm; + +} + +// Ships + +function _CreateRybb( + int renderPriority, invinTime, + float enmX, float enmY, float moveSpd + ){ + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + 1.5, 1.5, + largeEnemyAltHP, largeEnemyHitbox*2, 0, + texEnm, + rybbRect[0], rybbRect[1], rybbRect[2], rybbRect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + ObjMove_SetSpeed(enm, moveSpd); + ObjMove_SetAngle(enm, 90); + ObjRender_SetAngleZ(enm, 180); + + float x = 0, y = 0; + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + + wait(invinTime); + + ObjEnemy_SetDamageRate(enm, 100, 100); + ObjEnemy_SetAutoDelete(enm, true); + + } + + async{ + + while(!Obj_IsDeleted(enm)){ + + x = ObjMove_GetX(enm); + y = ObjMove_GetY(enm); + + yield; + } + + if( + (-128 < x && x < STG_WIDTH+128) + && + (y < STG_HEIGHT+128) + ) + { + DeleteShotInCircle(TYPE_SHOT, TYPE_ITEM, x, y, 256); + ObjSound_Play(bossBoom); + TExplosionA(x, y, 10, 0.5); + } + + } + + _EnemyItemDrop( + enm, false, + verylargeFlyingEnm_itemPointMin, largeEnm_itemChainMin, verylargeGroundEnm_itemAmmoMin, + verylargeFlyingEnm_itemPointMax, largeEnm_itemChainMax, verylargeGroundEnm_itemAmmoMax, + invinTime*2, largeEnemyHitbox*4 + ); + + return enm; + +} + +function _CreateDecker( + int renderPriority, invinTime, + float enmX, float enmY, float moveSpd + ){ + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + 1.5, 1.5, + largeEnemyAltHP, largeEnemyHitbox*2, 0, + texEnm, + deckerRect[0], deckerRect[1], deckerRect[2], deckerRect[3]); + + Obj_SetRenderPriorityI(enm, renderPriority); + + ObjRender_SetAngleZ(enm, 180); + + float x = 0, y = 0; + + async{ + + while(!Obj_IsDeleted(enm)){ + + x = ObjMove_GetX(enm); + y = ObjMove_GetY(enm); + + yield; + } + + if( + (-128 < x && x < STG_WIDTH+128) + && + (y < STG_HEIGHT+128) + ) + { + DeleteShotInCircle(TYPE_SHOT, TYPE_ITEM, x, y, 256); + ObjSound_Play(bossBoom); + TExplosionA(x, y, 10, 0.5); + } + + } + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + + wait(invinTime); + + ObjEnemy_SetDamageRate(enm, 100, 100); + ObjEnemy_SetAutoDelete(enm, true); + + } + + _EnemyItemDrop( + enm, false, + verylargeFlyingEnm_itemPointMin, largeEnm_itemChainMin, verylargeGroundEnm_itemAmmoMin, + verylargeFlyingEnm_itemPointMax, largeEnm_itemChainMax, verylargeGroundEnm_itemAmmoMax, + invinTime*2, largeEnemyHitbox*4 + ); + + return enm; + +} + +// Formation 2 + +task _SmallFairyRing( + int renderPriority, int graphicBullet, + float enmX, enmY, + int denseRing, float delayRing, float speedRing, + float spdMove, angMove, scaleBullet + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + smallEnemyScale, smallEnemyScale, + smallEnemyHP, smallEnemyHitbox, 0, + texEnm, + 768, 0, 1024, 256); + + Obj_SetRenderPriorityI(enm, renderPriority); + + ObjMove_SetSpeed(enm, spdMove); + ObjMove_SetAngle(enm, angMove); + + ObjEnemy_SetDamageRate(enm, 0, 0); + + wait(5); + + ObjEnemy_SetAutoDelete(enm, true); + + async{ + + wait(5); + + while(ObjEnemy_GetInfo(enm, INFO_LIFE) > 0){ + + if(ObjMove_GetX(enm) < STG_WIDTH && ObjMove_GetX(enm) > 0){ + + ascent(i in -1..denseRing){ + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), speedRing, GetAngleToPlayer(enm)+i*360/denseRing, graphicBullet, 10); + + _BulletRescale(bullet, scaleBullet, true, 1); + _Delay(bullet, 10); + + if(ObjEnemy_GetInfo(enm, INFO_LIFE) <= 0){Obj_Delete(bullet);} + else{ + Shoot1; + } + + } + + wait(delayRing); + + } + + else{yield;} + + } + + } + + _EnemyItemDrop( + enm, true, + 5, 3, + 10+(GetCommonDataPtr(RANK_PTR, 1)-1)*2, 6+(GetCommonDataPtr(RANK_PTR, 1)-1)*1, + 120, smallEnemyHitbox*2 + ); + +} + +// Enemy Type 2 : Jack o Lanterns (ground enemies) + +// Formation 1: Groups of 8 mini-lanterns. Does nothing. +// Formation 2: Groups of 4 midsize-lanterns. Fires aimed fans. + +task _CreateLanternSmall( + int renderPriority, int graphicBullet, + float angspaceFan, float speedFan1, float speedFan2, int widthFan, int stackFan, int delayFan, + float enmX, enmY, speedMove, scaleBullet + ){ + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + popcornScale, popcornScale, + popcornHP, popcornHitbox, 0, + texEnm, + 1024, 512, 1280, 768); + + Obj_SetRenderPriorityI(enm, renderPriority); + + ObjMove_SetSpeed(enm, speedMove); + ObjMove_SetAngle(enm, 90); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + + wait(15); + + ObjEnemy_SetAutoDelete(enm, true); + + } + + _EnemyItemDrop( + enm, false, + 6, 8, + 10+round((GetCommonDataPtr(RANK_PTR, 1)-1)*1.5), 12+(GetCommonDataPtr(RANK_PTR, 1)-1)*1.5, + 120, popcornHitbox*2 + ); + +} + +task _CreateLanternMid( + int renderPriority, int graphicBullet, + float angspaceFan, float speedFan1, float speedFan2, int widthFan, int stackFan, int delayFan, + float enmX, enmY, speedMove, scaleBullet + ){ + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + smallEnemyScale, smallEnemyScale, + smallEnemyHP, smallEnemyHitbox, 0, + texEnm, + 1280, 768, 1536, 1024); + + Obj_SetRenderPriorityI(enm, renderPriority); + + ObjMove_SetSpeed(enm, speedMove); + ObjMove_SetAngle(enm, 90); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + + wait(15); + + ObjEnemy_SetAutoDelete(enm, true); + + } + + async{ + + wait(speedMove*2); + + while(ObjEnemy_GetInfo(enm, INFO_LIFE) > 0){ + + if(ObjMove_GetY(enm) < 10*STG_HEIGHT/12-100 && ObjMove_GetY(enm) > STG_HEIGHT/9){ + + int bullet = CreateFan(enm, widthFan, graphicBullet, stackFan, + 0, angspaceFan, speedFan1, speedFan2, scaleBullet, + PATTERN_FAN_AIMED, false); + + if(ObjEnemy_GetInfo(enm, INFO_LIFE) <= 0){Obj_Delete(bullet);} + else{ + Shoot1; + } + + wait(delayFan); + + } + + else{yield;} + + } + + } + + _EnemyItemDrop( + enm, false, + 12, 10, + 20+round((GetCommonDataPtr(RANK_PTR, 1)-1)*1.5), 16+(GetCommonDataPtr(RANK_PTR, 1)-1)*2, + 120, smallEnemyHitbox*2 + ); + +} + +task _SmallLanternFormation( + int renderEnm, int graphicBullet, + float padX, float padY, + float angspaceFan, float speedFan1, float speedFan2, int widthFan, int stackFan, int delayFan, float scaleBullet, + float speedMove + ){ + + float offsetX = 80; + float offsetY = 70; + + int enmPad = _CreateEnemy( + false, + padX, padY, padX, padY, 5, + 1, 1, + 999, 0, 0, + texEnm, + 1536, 256, 2048, 768); + + Obj_SetRenderPriorityI(enmPad, renderEnm-4); + + ObjMove_SetSpeed(enmPad, speedMove); + ObjMove_SetAngle(enmPad, 90); + + ObjEnemy_SetDamageRate(enmPad, 0, 0); + + wait(5); + + ObjEnemy_SetAutoDelete(enmPad, true); + + async{ + + _CreateLanternSmall( + renderEnm, graphicBullet, + angspaceFan, speedFan1, speedFan2, widthFan, stackFan, delayFan, + padX+offsetX, padY+offsetY, speedMove, scaleBullet + ); + _CreateLanternSmall( + renderEnm, graphicBullet, + angspaceFan, speedFan1, speedFan2, widthFan, stackFan, delayFan, + padX-offsetX, padY+offsetY, speedMove, scaleBullet + ); + + _CreateLanternSmall( + renderEnm-1, graphicBullet, + angspaceFan, speedFan1, speedFan2, widthFan, stackFan, delayFan, + padX+offsetX, padY-offsetY, speedMove, scaleBullet + ); + _CreateLanternSmall( + renderEnm-1, graphicBullet, + angspaceFan, speedFan1, speedFan2, widthFan, stackFan, delayFan, + padX-offsetX, padY-offsetY, speedMove, scaleBullet + ); + + } + +} + +task _MidLanternFormation( + int renderEnm, int graphicBullet, + float padX, float padY, + float angspaceFan, float speedFan1, float speedFan2, int widthFan, int stackFan, int delayFan, float scaleBullet, + float speedMove + ){ + + int enmPad = _CreateEnemy( + false, + padX, padY, padX, padY, 5, + 0.75, 0.75, + 999, 0, 0, + texEnm, + 1536, 256, 2048, 768); + + Obj_SetRenderPriorityI(enmPad, renderEnm-4); + + ObjMove_SetSpeed(enmPad, speedMove); + ObjMove_SetAngle(enmPad, 90); + + ObjEnemy_SetDamageRate(enmPad, 0, 0); + + wait(5); + + ObjEnemy_SetAutoDelete(enmPad, true); + + async{ + + _CreateLanternMid( + renderEnm, graphicBullet, + angspaceFan, speedFan1, speedFan2, widthFan, stackFan, delayFan, + padX-90, padY, speedMove, scaleBullet + ); + _CreateLanternMid( + renderEnm, graphicBullet, + angspaceFan, speedFan1, speedFan2, widthFan, stackFan, delayFan, + padX+90, padY, speedMove, scaleBullet + ); + + } + +} + +// Enemy Type 3: Will o the Wisps + +// Formation 1: Appears randomly on the top of the screen, slowly moving down while firing slow aimed bullets. +// Formation 2: Flies from either side, moving horizontally. Fires bullets aimed straight down. + +function _SmallWisp( + int renderPriority, spawnTime, invinTime, + float enmX, enmY, spdMove, angMove, int graphicBullet, + int delayBullet, int bulletAccelTime, float maxspeedBullet, float bulletAng, float scaleBullet + ){ + + // Spawns enemy. + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, spawnTime, + smallEnemyScale*0.5, smallEnemyScale, + smallEnemyHP, smallEnemyHitbox, 0, + texEnm, + 768, 0, 1024, 256); + + Obj_SetRenderPriorityI(enm, renderPriority); + + ObjMove_SetSpeed(enm, 0); + ObjMove_SetAngle(enm, angMove); + + async{ + + ObjEnemy_SetDamageRate(enm, 0, 0); + + wait(spawnTime); + + ObjEnemy_SetAutoDelete(enm, true); + + wait(invinTime - spawnTime); + + ObjEnemy_SetDamageRate(enm, 100, 100); + + } + + async{ + + wait(spawnTime); + + ObjMove_SetSpeed(enm, spdMove); + + while(ObjEnemy_GetInfo(enm, INFO_LIFE) > 0){ + + if(ObjMove_GetX(enm) < STG_WIDTH && ObjMove_GetX(enm) > 0){ + + int bullet = CreateShotA2(ObjMove_GetX(enm) + rand(-30, 30), ObjMove_GetY(enm) + rand(-30, 30), 0, bulletAng, maxspeedBullet/bulletAccelTime, maxspeedBullet, graphicBullet, 10); + + _BulletRescale(bullet, scaleBullet, true, 1); + _Delay(bullet, 10); + + if(ObjEnemy_GetInfo(enm, INFO_LIFE) <= 0){Obj_Delete(bullet);} + else{ + Shoot1; + } + + wait(delayBullet); + + } + + else{yield;} + + } + + } + + _EnemyItemDrop( + enm, true, + 5, 5, + 10+(GetCommonDataPtr(RANK_PTR, 1)-1)*2, 10+(GetCommonDataPtr(RANK_PTR, 1)-1)*1, + 120, smallEnemyHitbox*2 + ); + + return enm; + +} + +// Enemy Type 4: Oni + +function _CreateOni( + int renderPriority, int graphicBullet, bool bombdrop, + float delayBullet, float speedBullet, float acceltimeBullet, + float enmX, enmY, speedMoveEnm, scaleBullet + ){ + + // Enemy has NO GRAPHIC + + int enm = _CreateEnemy( + enmX, enmY, enmX, enmY, 5, + largeEnemyScale, largeEnemyScale, + largeEnemyHP, largeEnemyHitbox, 0, + texEnm, + 0, 256, 256, 512); + + Obj_SetRenderPriorityI(enm, renderPriority); + + ObjMove_SetSpeed(enm, speedMoveEnm); + ObjMove_SetAngle(enm, 90); + + ObjEnemy_SetDamageRate(enm, 0, 0); + + async{ + + if(GetCommonData("Flying Loops Cleared", 0) % 2 == 0 && GetCommonData("Flying Loops Cleared", 0) != 0 && bombdrop){ + + int sigil = _Create2DImage(texEnm, [0, 1024, 512, 1536]); + ObjRender_SetAlpha(sigil, 180); + Obj_SetRenderPriorityI(sigil, Obj_GetRenderPriorityI(enm)-1); + + while(ObjEnemy_GetInfo(enm, INFO_LIFE) > 0){ + ObjRender_SetPosition(sigil, ObjMove_GetX(enm), ObjMove_GetY(enm), 1); + ObjRender_SetAngleZ(sigil, ObjRender_GetAngleZ(sigil)+3); + yield; + } + + Obj_Delete(sigil); + + } + + } + + async{ + + async{ + + float x = 0, y = 0; + + async{ + wait(max(5, 10-GetCommonData("Rank", 0)*5)); + while(ObjEnemy_GetInfo(enm, INFO_LIFE) > 0){ + x = ObjMove_GetX(enm); + y = ObjMove_GetY(enm); + yield; + } + } + + wait(max(25, 60-GetCommonData("Rank", 1)*5)); + + while(ObjEnemy_GetInfo(enm, INFO_LIFE) > 0){yield;} + + if( + (-128 < x && x < STG_WIDTH+128) + && + (y < STG_HEIGHT+128) + ) + { + //DeleteShotInCircle(TYPE_SHOT, TYPE_ITEM, x, y, 384); + //ObjSound_Play(bossBoom); + if(GetCommonData("Flying Loops Cleared", 0) % 2 == 0 && GetCommonData("Flying Loops Cleared", 0) != 0 && bombdrop){CreateExtendItem(EXTEND_SPELL, x, y);} + TExplosionA(x, y, 10, 0.5); + } + + } + + wait(max(10, 20-GetCommonData("Rank", 1)*2)); + + ObjEnemy_SetAutoDelete(enm, true); + + async{ + + wait(5); + + while(ObjEnemy_GetInfo(enm, INFO_LIFE) > 0){ + + if(ObjMove_GetY(enm) < 11*STG_HEIGHT/12 && ObjMove_GetY(enm) > STG_HEIGHT/12){ + + float xspd = rand(-(2+GetCommonDataPtr(RANK_PTR, 1)*0.25), 2+GetCommonDataPtr(RANK_PTR, 1)*0.25); + int bullet = CreateShotB2(ObjMove_GetX(enm), ObjMove_GetY(enm), xspd, -speedBullet, 0, speedBullet/(acceltimeBullet/2), xspd, speedBullet*1.5, graphicBullet, 10); + + if(Obj_IsDeleted(enm)){Obj_Delete(bullet); break;} + + else{ + + Shoot1; + _BulletRescale(bullet, scaleBullet, true, 1); + _Delay(bullet, 10); + + } + + wait(delayBullet); + + } + + else{yield;} + + yield; + + } + + } + + _EnemyItemDrop( + enm, false, + 18, 15, + round(30+(GetCommonDataPtr(RANK_PTR, 1)-1)*1.5), round(24+(GetCommonDataPtr(RANK_PTR, 1)-1)*1.5), + 180, largeEnemyHitbox*2.5 + ); + + } + + return enm; + //ObjEnemy_SetDamageRate(enm, 100, 150); + +} + +*/ \ No newline at end of file diff --git a/script/Jam10/NarumiSTG.dnh b/script/Jam10/NarumiSTG.dnh new file mode 100644 index 0000000..a27663f --- /dev/null +++ b/script/Jam10/NarumiSTG.dnh @@ -0,0 +1,2161 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["Winter Games"] +#Text["This bitch empty - would you like to yeet?"] +#System["script/KevinSystem/Kevin_System.txt"] + +float rank = 1; // Increases through time + +let RANK_PTR = LoadCommonDataValuePointer("Rank", 1); + +let objScene = GetEnemyBossSceneObjectID(); +let csd = GetCurrentScriptDirectory(); + +let bossObj; + +float bossX = 0; +float bossY = 0; +float playerY = 0; +float playerX = 0; + +bool bossIntro = false; + +let spellsnd = ObjSound_Create(); +let bossdiesnd = ObjSound_Create(); + +int[] enmFly = []; +int[] enmGround = []; + +int[] rankAvg = []; + +let POINTER_CHAIN = LoadAreaCommonDataValuePointer("PIV", "ChainAmount", 1); + +//let SYSTEMID_PTR_2 = LoadAreaCommonDataValuePointer("ScriptID", "SystemID", 0); + +// Includes ahoy + +#include "script/KevinSystem/Universal_Lib.txt" +#include "script/Jam10/GunnerParade_EnmLib.dnh" +#include "script/Jam10/GunnerParade_ConstLib.dnh" +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" + +@Initialize { + + //SetIntersectionVisualization(true); + + SetAutoDeleteObject(true); + + SetCommonData("Rank", clamp(GetCommonData("Rank", 1), RANK_MIN, RANK_MAX)); + //difficultySelect = _InitDifficulty(difficultySelect); + + //difficultySelect = 2; // debug + + if(!IsCommonDataAreaExists("PIV")){ + CreateCommonDataArea("PIV"); + SetAreaCommonData("PIV", "currentvalue", 10000); + } + else{} + + // Create the boss object itself + bossObj = ObjEnemy_Create(OBJ_ENEMY_BOSS); + ObjEnemy_Regist(bossObj); + + ObjMove_SetPosition(bossObj, STG_WIDTH/2, -256); + + ObjEnemy_SetDamageRate(bossObj, 0, 0); + + _RenderBossFight(bossObj); + SetEnemyAutoDeleteClip(160, 160, 160, 160); + + //testTask(); + + //groundTask(); + flyingTask(); + //UpdateDrops(); + + bossFight(); + + curEnmManage(); + + //SetCommonData("Rank", 9); + + //_FadeInvincibility(bossObj, 150, 150, 1); + //endingnew(); +} + +@Event { + + alternative(GetEventType()) + + case(EV_REQUEST_LIFE) { + SetScriptResult(HP_MAX); + } + + case(EV_REQUEST_IS_DURABLE_SPELL) { + SetScriptResult(false); + } + + case(EV_REQUEST_TIMER) { + SetScriptResult(STAGE_LENGTH); + //SetScriptResult(BOSS_LENGTH+5); + } + +} + +@MainLoop { + + playerY = GetPlayerY(); + playerX = GetPlayerX(); + //The player position is ALWAYS UPDATED + + bossX = ObjMove_GetX(bossObj); + bossY = ObjMove_GetY(bossObj); + + ObjEnemy_SetIntersectionCircleToShot(bossObj, ObjMove_GetX(bossObj), ObjMove_GetY(bossObj), 192); + + yield; + +} + +@Finalize { + +} + + +// This array contains ONLY FLYING ENEMIES + +task groundTask(){ + + wait(90); + + while(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) > BOSS_LENGTH){ + + WaveGround1(); + wait(max(5, 15-rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + if(GetCommonData("Ground Loops Cleared", 0)/3 == 0 && rank > 3){ + + WaveGround2(playerX); + wait(max(5, 15-rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + SetCommonData("Rank", clamp(GetCommonData("Rank", 1)+0.5, 1, RANK_MAX)); + + } + + SetCommonData("Ground Loops Cleared", GetCommonData("Ground Loops Cleared", 0)+1); + + yield; + + } + +} + +task flyingTask(){ + + wait(30); + + while(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) > BOSS_LENGTH){ + + Wave1(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + Wave2(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + if(rank > 4 || GetCommonData("Flying Loops Cleared", 0) > 3){ + WaveGround1(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + } + + Wave3(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + Wave5(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + SetCommonData("Rank", clamp(GetCommonData("Rank", 1)+0.5, 1, RANK_MAX)); + + Wave4(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + Wave1(); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + + if(rank > 7 || GetCommonData("Flying Loops Cleared", 0) > 5){ + WaveGround2(playerX); + wait(max(5, 20-4*rank)); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= BOSS_LENGTH){break;} + } + + SetCommonData("Flying Loops Cleared", GetCommonData("Flying Loops Cleared", 0)+1); + SetCommonData("Rank", clamp(GetCommonData("Rank", 1)+0.5, 1, RANK_MAX)); + + yield; + } + +} + + +task curEnmManage(){ + + SetCommonData("Flying Loops Cleared", 0); + SetCommonData("Ground Loops Cleared", 0); + + RankManagement(); + + int[] allEnm = []; + + while(true){ + enmGround = []; + enmFly = []; + allEnm = GetIntersectionRegistedEnemyID(); + for each (int enm in ref allEnm){ + if(Obj_GetRenderPriorityI(enm) <= 37){enmGround ~= [enm];} + else if(Obj_GetRenderPriorityI(enm) >= 38 && Obj_GetRenderPriorityI(enm) < 41){enmFly ~= [enm];} + else{} + } + wait(10); + } + +} + +task _BossExplosion(){ + + float enmX = 0, enmY = 0; + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + + enmX = ObjMove_GetX(bossObj); enmY = ObjMove_GetY(bossObj); + + yield; + + } + + //NotifyEventAll(EV_DROP_POINT_ENEMY, [enmX, enmY], timer, maxTimer, minPoint, maxPoint); + + DeleteShotAll(TYPE_ALL, TYPE_ITEM); + SetPlayerInvincibilityFrame(300); + ObjSound_Play(bossBoom); + Obj_SetRenderPriorityI(bossObj, 30); + NotifyEvent(GetCommonDataPtr(SYSTEMID_PTR, 0), EV_EXPLODE, [enmX, enmY]); + + _ObjShake(bossObj, 190, 60); + + loop(30){ + //LoadEx(bossBoom, "script/game/resourceLib/bigBoom.ogg", 30 * SFXVol); + ObjSound_Play(bossBoom); + NotifyEvent(GetCommonDataPtr(SYSTEMID_PTR, 0), EV_EXPLODE, [bossX+rand(-240, 240), bossY+rand(-150, 150)]); + wait(6); + } + + ObjMove_SetDestAtFrame(bossObj, bossX, STG_HEIGHT+512, 120, LERP_ACCELERATE); + + float ang = ObjRender_GetAngleZ(bossObj); + + ascent(i in 0..120){ + ObjRender_SetAngleZ(bossObj, Interpolate_Accelerate(ang, ang+180, i/120)); + yield; + } + + //wait(); + + _EndShake(120, 90); + + loop(120){ + NotifyEvent(GetCommonDataPtr(SYSTEMID_PTR, 0), EV_EXPLODE, [bossX+rand(-240, 240), STG_HEIGHT+rand(0, -150)]); + } + + ObjSound_Play(bossBoom); + + EndBonus(); + + //_ScorePopup(float enmX, float enmY, int pointNum, int pivNum); + + // NotifyEvent is faster than NotifyEventAll, considering how the item event will be called many times. + +} + +task EndBonus(){ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + //WriteLog(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER)); + //wait(30); + yield; + } + + ObjEnemy_SetLife(bossObj, -1); + + let timer = ObjEnemyBossScene_GetInfo(objScene, INFO_TIMERF); + //WriteLog(timer); + + // Bonus Calculations: + + // (Time Remaining + Ground Loops Cleared + Flying Loops Cleared + Average Rank) * 10000 + + function _CreateBonusText(float x, y, fontSize, int colorBorder, string text){ + + int objText = CreateTextObject( + + x, y, fontSize, + "", "GravityRegular5", + 0xFFFFFF, 0xFFFFFF, + colorBorder, 4, + 71 + + ); + + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER); + + TTextScroll(objText, text); + + } + + wait(120); + + float rankAvgFinal = 0; + float rankSum = 0; + + ascent(i in -1..length(rankAvg)-1){ + rankSum += rankAvg[i]; + } + + rankAvgFinal = rankSum/length(rankAvg); + + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2-220, 30, 0xCF007A, "LIVES REMAINING: " ~ IntToString(GetPlayerLife())); + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2-180, 30, 0x3500CF, "TIME REMAINING: " ~ vtos("5.2f", timer/60)); + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2-140, 30, 0xCF6100, "ENEMIES DEFEATED: " ~ IntToString(GetCommonDataPtr(GROUNDENM_PTR, 0) + GetCommonDataPtr(FLYINGENM_PTR, 0))); + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2-100, 30, 0xCF0000, "AVERAGE RANK LV: " ~ vtos("5.2f", rankAvgFinal)); + + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2, 30, 0xFFA300, "END BONUS:"); + + wait(120); + + float multiplierBonus = (GetPlayerLife() + timer/60 + GetCommonDataPtr(GROUNDENM_PTR, 0)/5 + GetCommonDataPtr(FLYINGENM_PTR, 0)/5 + rankAvgFinal) * 30; + + int scoreBonus = (trunc ( (multiplierBonus * 100000) / 100 ) * 10); + + _CreateBonusText(STG_WIDTH/2, STG_HEIGHT/2+60, 60, 0xFFA300, DigitToCommaArray(scoreBonus)); + AddScore(scoreBonus); + + wait(60); + + if(!IsReplay()){SetCommonData("Run Score", GetScore());} + else{SetCommonData("Run Score", 0);} + + Obj_Delete(bossObj); + CloseScript(GetOwnScriptID()); + +} + +task RankManagement(){ + + //SetCommonData("Rank", 9); + //SetCommonData("Rank", 10); + // Rank increase + let textRank = CreateTextObject( + STG_WIDTH-15, STG_HEIGHT/14, 24, + "RANK:", "GravityBold8", + 0xFFFFFF, 0xFFFFFF, + 0xAE22FF, 5, + 71 + ); + + ObjText_SetHorizontalAlignment(textRank, ALIGNMENT_RIGHT); + + async{ + while(true){ + rank = trunc(GetCommonData("Rank", 1)); + if(rank >= RANK_MAX){ObjText_SetText(textRank, "RANK LV [font sz=32 oc=(193, 0, 99)]MAX");} + else{ObjText_SetText(textRank, "RANK LV [font sz=45 oc=(193, 0, 99)]" ~ IntToString(rank));} + //SetCommonData("Rank", 9); + wait(45); + } + } + + async{ + while(true){ + if(ObjMove_GetY(GetPlayerObjectID()) < GetStgFrameHeight()/6){ + ObjRender_SetAlpha(textRank, 60); + } + else{ + ObjRender_SetAlpha(textRank, 255); + } + yield; + } + } + + async{ + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + rankAvg ~= [rank]; + wait(60); + } + } + + // Per frame rank increase. +1 rank per 10 seconds (+0.1 rank per second, +1/600 rank per frame), rank 10 at 100 seconds if no specials, bombs or deaths happen + + async{ + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + SetCommonDataPtr(RANK_PTR, clamp(GetCommonDataPtr(RANK_PTR, 1)+1/600, RANK_MIN, RANK_MAX_TRUE)); + yield; + } + } + + // Rank on HUD + + async{ + let textRank = CreateTextObject( + 1500, 660, 48, + "", "Origami Mommy", + 0xFF9294, 0xFFFFFF, + 0x8F0507, 8, + 19 + ); + + ObjText_SetHorizontalAlignment(textRank, ALIGNMENT_CENTER); + + let textRankRange = CreateTextObject( + 1820, 618, 24, + "", "Unispace", + 0xA9FFD0, 0xFFFFFF, + 0x8F0507, 2, + 19 + ); + + while(true){ + ObjText_SetText(textRank, IntToString(rank)); + ObjText_SetText(textRankRange, "LV." ~ IntToString(RANK_MIN) ~ "[r][font oy=4 tc=(255, 114, 189)]LV." ~ IntToString(RANK_MAX_TRUE) ~ "[r][font oy=8 tc=(255, 147, 138)]" ~ rtos("00.00", GetCommonData("Rank", 1))); + yield; + } + } + +} + +task testTask(){ + + wait(15); + + while(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) > 20){ + + Wave5(); + + SetCommonData("Rank", clamp(GetCommonData("Rank", 1)+1, 1, RANK_MAX)); + SetCommonData("Ground Loops Cleared", GetCommonData("Ground Loops Cleared", 0)+1); + SetCommonData("Flying Loops Cleared", GetCommonData("Flying Loops Cleared", 0)+1); + + yield; + } + +} + +///////////// BOSS HANDLING ///////////// + +task bossFight(){ + + while(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMERF) > BOSS_LENGTH*60){ + + yield; + + } + + NotifyEventAll(EV_BOSS_MUSIC, 1); + bossIntro = true; + + BossIntro(); + BossPhase1(); // Rings + BossPhase2(); + //BossPhase3(); + + // Umbrella waves + + return; + +} + +function BossIntro(){ + + bool bossCurrentlyIntro = true; + + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH * 3/4, STG_HEIGHT/2, 60, LERP_DECELERATE); + + async{ + + int timer = ObjEnemyBossScene_GetInfo(objScene, INFO_TIMERF); + + while(bossCurrentlyIntro){ + ObjEnemyBossScene_SetSpellTimer(objScene, timer); + SetForbidPlayerShot(true); + SetForbidPlayerSpell(true); + ObjEnemy_SetDamageRate(bossObj, 0, 0); + yield; + } + + SetForbidPlayerShot(false); + SetForbidPlayerSpell(false); + ObjEnemy_SetDamageRate(bossObj, 0, 0); + + } + + wait(60); + + bossCurrentlyIntro = false; + +} + + +function BossPhase1(){ + + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH * 3/4, STG_HEIGHT/2, 60, LERP_DECELERATE); + wait(10); + + _FadeInvincibility(bossObj, 90, 90, 0.5); + + int dense = FUNC_LERP_LINEAR(12, 15, rank/RANK_MAX); + int del1 = FUNC_LERP_LINEAR(5, 3, rank/RANK_MAX); + int del2 = FUNC_LERP_LINEAR(80, 60, rank/RANK_MAX); + int ringNum = FUNC_LERP_LINEAR(6, 9, rank/RANK_MAX); + int accelTime = FUNC_LERP_LINEAR(30, 25, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(10, 13, rank/RANK_MAX); + float angStart = rand(0, 360); + + PhaseBonusCalculation(PHASE1_LIMIT, "[font oc=(98, 0, 164) wg=800]Withering Flower"); + + async{ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE1_LIMIT){ + + float baseAng = rand(0, 360); + + ascent(i in 0..ringNum){ + + float ang = baseAng + 180/ringNum * i; + float[] ringPos = [bossX + sin(ang) * 60, bossY + cos(ang) * 60]; + + Shoot2; + + ascent(k in 0..dense){ + int bullet = CreateShotA2(ringPos[0], ringPos[1], spd, k * 360/dense, -spd/accelTime, 0, KEV_LEAF_AQUA, 10); + ObjMove_AddPatternA2(bullet, accelTime*1.25, NO_CHANGE, NO_CHANGE, spd/accelTime, spd, 0); + _Delay(bullet, 10); + } + + wait(del1); + + } + + wait(del2-30); + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH*3/4 + rand(-128, 192), playerY, 30, LERP_DECELERATE); + wait(30); + + } + + } + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE1_LIMIT){ + + yield; + + } + + ObjEnemy_SetDamageRate(bossObj, 0, 0); + DeleteShotAll(TYPE_ALL, TYPE_ITEM); + + wait(60); + + return; + +} + +// Phase 2: Travelers Clad in White +function BossPhase2(){ + + int fanDense = FUNC_LERP_LINEAR(3, 6, rank/RANK_MAX); + int fanStack = FUNC_LERP_LINEAR(2, 4, rank/RANK_MAX); + int fanRange = FUNC_LERP_LINEAR(4, 7, rank/RANK_MAX); + int del = FUNC_LERP_LINEAR(45, 60, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(8, 11, rank/RANK_MAX); + float moveSpd = FUNC_LERP_ACCEL(3, 6, rank/RANK_MAX); + + float ang = 180; + + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH * 5/6, STG_HEIGHT/2, 60, LERP_DECELERATE); + + _FadeInvincibility(bossObj, 90, 90, 0.5); + + PhaseBonusCalculation(PHASE2_LIMIT, "[font oc=(98, 0, 164) wg=800]Travelers Clad in White"); + + async{ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE2_LIMIT){ + ObjMove_SetY(bossObj, STG_HEIGHT/2 + STG_HEIGHT/5 * sin(ang)); + ang += moveSpd; + yield; + } + + ObjEnemy_SetDamageRate(bossObj, 0, 0); + DeleteShotAll(TYPE_ALL, TYPE_ITEM); + + _BossExplosion(); + + } + + async{ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE2_LIMIT){ + + WaveGround2(playerX); + //wait(30); + + } + + } + + + async{ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE2_LIMIT){ + + CreateFan + (bossObj, fanDense, KEV_BALL_AQUA, fanStack, + 0, fanRange, spd, spd/1.1, 1, + 0, 0, + PATTERN_FAN_AIMED, false + ); + + wait(del); + + } + + } + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE2_LIMIT){ + + yield; + + } + + ObjEnemy_SetDamageRate(bossObj, 0, 0); + DeleteShotAll(TYPE_ALL, TYPE_ITEM); + + wait(45); + + return; + +} + +/* +function BossPhase3(){ + + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, STG_HEIGHT/5, 60, LERP_DECELERATE); + + PhaseBonusCalculation(PHASE3_LIMIT, "[font oc=(98, 0, 164) wg=800]Paving a Rainbow Sky"); + + _FadeInvincibility(bossObj, 90, 90, 0.25); + + wait(30); + + float numKilled = 0; + + // BIRD + + float bulletNum = FUNC_LERP_LINEAR(8, 12, rank/RANK_MAX); + float bulletSpd = FUNC_LERP_ACCEL(6.25, 7.25, rank/RANK_MAX); + float birdWvel = FUNC_LERP_ACCEL(1.2, 2, rank/RANK_MAX); + int bulletDel = FUNC_LERP_LINEAR(10, 5, rank/RANK_MAX); + int bulletWait = FUNC_LERP_LINEAR(45, 35, rank/RANK_MAX); + float birdSpd = FUNC_LERP_ACCEL(9, 11.2, rank/RANK_MAX); + float birdNum = FUNC_LERP_LINEAR(10, 15, rank/RANK_MAX); + int spawnDel = FUNC_LERP_ACCEL(80, 60, rank/RANK_MAX); + + // Bullet lines + + int linenum = FUNC_LERP_LINEAR(14, 17, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(4, 2, rank/RANK_MAX); + int del2 = FUNC_LERP_ACCEL(8, 5, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(9, 11, rank/RANK_MAX); + float ang = rand(80, 100); + + async{ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE3_LIMIT){yield;} + + ObjEnemy_SetDamageRate(bossObj, 0, 0); + DeleteShotAll(TYPE_ALL, TYPE_ITEM); + + _BossExplosion(); + + } + + task _SummonBirdEx(float startAng, float wvel, int num){ + + int umbrella = _SmallWitch( + 41, bulletDel * bulletNum, + bossX, bossY + ); + + bool isFinishMove = false; + + ObjMove_SetAngle(umbrella, startAng); + ObjRender_SetAngleZ(umbrella, startAng); + + ObjMove_SetAngularVelocity(umbrella, wvel); + + ObjMove_SetSpeed(umbrella, birdSpd); + + ObjMove_AddPatternA2(umbrella, 60, NO_CHANGE, NO_CHANGE, NO_CHANGE, NO_CHANGE, wvel/10); + + async{ + while(!Obj_IsDeleted(umbrella)){ + ObjRender_SetAngleZ(umbrella, ObjMove_GetAngle(umbrella)); + yield; + } + numKilled++; + ObjEnemy_SetDamageRate(bossObj, numKilled * 2.5, numKilled * 2.5); // 33 enemies put dmg rate to 100 + } + + int num2 = 0; + + ascent(i in 0..num){ + + float lerpNum1 = i; + float lerpNum2 = num; + + ObjEnemy_SetDamageRate(umbrella, FUNC_LERP_LINEAR(10, 50, lerpNum1/lerpNum2), FUNC_LERP_LINEAR(10, 50, lerpNum1/lerpNum2)); + + int color = KEV_LEAF_RED + num2; + + int bullet = CreateShotA1(ObjMove_GetX(umbrella), ObjMove_GetY(umbrella), 0, wvel < 0 ? ObjMove_GetAngle(umbrella) : ObjMove_GetAngle(umbrella), color, 5); + + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0 || Obj_IsDeleted(umbrella)){Obj_Delete(bullet);} + else{ + _Delay(bullet, 5); + _BulletRescale(bullet, 0.75, true, 0.25); + BulletAction(bullet, lerpNum1, lerpNum2); + Shoot1; + } + + wait(bulletDel); + + num2++; + if (num2 > (KEV_BALL_PINK - KEV_BALL_RED)){num2 = 0;} + } + + task BulletAction(ID, lerpNum1, lerpNum2){ + + while(!isFinishMove){yield;} + + if(Obj_IsDeleted(ID)){return;} + else{ + ObjMove_AddPatternA2(ID, 0, NO_CHANGE, NO_CHANGE, FUNC_LERP_LINEAR(bulletSpd/1.5, bulletSpd, lerpNum1/lerpNum2)/FUNC_LERP_LINEAR(bulletWait, bulletWait/1.5, lerpNum1/lerpNum2), FUNC_LERP_LINEAR(bulletSpd/1.5, bulletSpd, lerpNum1/lerpNum2), 0); + } + + } + + isFinishMove = true; + + ObjEnemy_SetDamageRate(umbrella, 100, 100); + + } + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > PHASE3_LIMIT){ + + float randAng = rand(0, 360); + + ascent(i in 0..birdNum){ + _SummonBirdEx(i * 360/birdNum + randAng, birdWvel, bulletNum); + } + + wait(spawnDel); + + randAng = rand(0, 360); + + ascent(i in 0..birdNum){ + _SummonBirdEx(i * 360/birdNum + randAng, -birdWvel, bulletNum); + } + + wait(spawnDel); + + } + + return; + +} +*/ + +task PhaseBonusCalculation(int HPthreshold, string spellName){ + + int curRank = rank; + int scoreBase = 1000000 * curRank; + int scoreBonus = GetAreaCommonData("PIV", "currentvalue", 1000)*100; + int i = 0; // 20 seconds + + function _CreateBonusText(float x, y, fontSize, int colorBorder, string text){ + + let objText = CreateTextObject( + + x, y, fontSize, + text, "GravityBold8", + 0xFFFFFF, 0xFFFFFF, + colorBorder, fontSize/10, + 71 + + ); + + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_RIGHT); + + return objText; + + } + + let scoreText = _CreateBonusText(STG_WIDTH-12, STG_HEIGHT/9+36, 24, 0x000000, ""); + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > HPthreshold){ + + scoreBase = trunc(Interpolate_Smooth(1000000 * curRank, 100000 * curRank, i/1200)/10)*10; + i = min(1200, i+1); + + scoreBonus = scoreBase * GetCommonDataPtr(POINTER_CHAIN, 1); + + ObjText_SetText(scoreText, spellName ~ "[r][font sz=16]BONUS: [font oc=(255, 136, 0)]" ~ IntToString(scoreBonus)); + + yield; + + } + + AddScore(scoreBonus); + + async{ + + ObjText_SetText(scoreText, "[font sz=32 oc=(164, 0, 90)]SCORE BONUS:[r][font sz=32 wg=800 oc=(255, 136, 0)]" ~ DigitToCommaArray(trunc(scoreBonus/10)*10)); + + ChargeBreakSFX; + + wait(60); + + Obj_Delete(scoreText); + + } + +} + + +///////////// ENEMY HANDLING (NOT BOSS) ///////////// + +/* +function WaveGround1(){ + + float speedMove = baseMoveSpeed1L * (1 + MoveSpeedRankMultiplierH * rank); + int invin = FUNC_LERP_DECEL(WG1_invinTimeMax, WG1_invinTimeMin, rank/RANK_MAX); + + _SignPlatform1( + 34, invin, + STG_WIDTH/4, -128, speedMove + ); + + wait(invin); + + while(length(enmGround) > 1){yield;} + + _SignPlatform1( + 34, invin, + 3*STG_WIDTH/4, -128, speedMove + ); + + wait(invin); + + while(length(enmGround) > 1){yield;} + + return; + +} + +function WaveGround1A(){ + + float speedMove = baseMoveSpeed1L * (1 + MoveSpeedRankMultiplierL * rank); + int invin = FUNC_LERP_DECEL(WG1A_invinTimeMax, WG1A_invinTimeMin, rank/RANK_MAX); + int num = FUNC_LERP_DECEL(WG1A_bulletNumMin, WG1A_bulletNumMax, rank/RANK_MAX); + float spd = FUNC_LERP_DECEL(WG1A_bulletSpdMin, WG1A_bulletSpdMax, rank/RANK_MAX); + float del = FUNC_LERP_DECEL(WG1A_bulletDelayMin, WG1A_bulletDelayMax, rank/RANK_MAX); + + int[] signs1 = _SignPlatform1A( + 34, invin, + 2*STG_WIDTH/7-64, -128, speedMove + ); + + for each (int sign in ref signs1){ + Atk(sign); + } + + int[] signs2 = _SignPlatform1A( + 34, invin, + 5*STG_WIDTH/7+64, -128, speedMove + ); + + for each (int sign in ref signs2){ + Atk(sign); + } + + task Atk(int ID){ + + async{ + while(!Obj_IsDeleted(ID) && ObjMove_GetY(ID) <= STG_HEIGHT - 128 && GetObjectDistance(ID, GetPlayerObjectID()) > popcornHitbox * 2){ + + CreateFan( + ID, num, KEV_BALL_PINK, 1, + GetAngleToPlayer(ID), 2.25, spd, spd/1.5, 0.75, + ObjMove_GetX(ID), ObjMove_GetY(ID), + PATTERN_FAN, false + ); + + wait(del); + + } + } + + } + + wait(invin); + + while(length(enmGround) > 1){yield;} + + return; + +} + +function WaveGround2(){ + + float speedMove = baseMoveSpeedVL * (1 + MoveSpeedRankMultiplierL * rank); + int invin = FUNC_LERP_DECEL(WG2_invinTimeMax, WG2_invinTimeMin, rank/RANK_MAX); + + int del = FUNC_LERP_DECEL(WG2_bulletDelayMax, WG2_bulletDelayMin, rank/RANK_MAX); + int num = FUNC_LERP_DECEL(WG2_bulletNumMin, WG2_bulletNumMax, rank/RANK_MAX); + float spd = FUNC_LERP_DECEL(WG2_bulletSpdMin, WG2_bulletSpdMax, rank/RANK_MAX); + float space = FUNC_LERP_DECEL(WG2_angRangeMin, WG2_angRangeMax, rank/RANK_MAX); + + float aimAng = 0; + + task Atk(int ID){ + + async{ + while(!Obj_IsDeleted(ID) && ObjMove_GetY(ID) <= STG_HEIGHT * 6/7 && GetObjectDistance(ID, GetPlayerObjectID()) > popcornHitbox * 3){ + + float posX = 128 * cos(GetAngleToPlayer(ID)); + float posY = 128 * sin(GetAngleToPlayer(ID)); + + CreateFan( + ID, num, KEV_FIRE_RED, 1, + GetAngleToPlayer(ID), space, spd, spd/1.5, 1, + posX, posY, + PATTERN_FAN, false + ); + + wait(del); + + } + } + + while(!Obj_IsDeleted(ID)){ + ObjRender_SetAngleZ(ID, atan2(playerY - ObjMove_GetY(ID), playerX - ObjMove_GetX(ID))); + aimAng = atan2(playerY - ObjMove_GetY(ID), playerX - ObjMove_GetX(ID)); + yield; + } + } + + int[] enmArr = _CreateCannonBush( + 35, invin, + 2*STG_WIDTH/7, -128, speedMove + ); + + for each(int enm in ref enmArr){ + Atk(enm); + } + + wait(invin); + + while(length(enmGround) > 0){yield;} + + int[] enmArr2 = _CreateCannonBush( + 34, invin, + 5*STG_WIDTH/7, -128, speedMove + ); + + for each(int enm in ref enmArr2){ + Atk(enm); + } + + wait(invin); + + while(length(enmGround) > 0){yield;} + + return; + +} + +// Rybb + +function WaveGround3(){ + + float speedMove = baseMoveSpeedVL * (1 + MoveSpeedRankMultiplierVL * rank); + + int dense = FUNC_LERP_DECEL(WG3_spiralDenseMin, WG3_spiralDenseMax, rank/RANK_MAX); + int num = FUNC_LERP_DECEL(WG3_spiralNumMin, WG3_spiralNumMax, rank/RANK_MAX); + int del = FUNC_LERP_DECEL(WG3_spiralDelayMax, WG3_spiralDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_DECEL(WG3_spiralSpdMin, WG3_spiralSpdMax, rank/RANK_MAX); + + int ship = _CreateRybb( + 36, del*3, + playerX, -180, speedMove + ); + + async{ + + while(!Obj_IsDeleted(ship)){ + + if (ObjMove_GetY(ship) <= 0) {ObjEnemy_SetDamageRate(ship, 0, 0);} + else if (ObjMove_GetY(ship) <= FUNC_LERP_LINEAR(180, 60, rank/RANK_MAX)) {ObjEnemy_SetDamageRate(ship, 25, 0);} + else {ObjEnemy_SetDamageRate(ship, 100, 100);} + + yield; + + } + + } + + int i = 0; + float startAng = 0; + + while(!Obj_IsDeleted(ship)){ + + int dir = i % 2 == 0 ? 1 : -1; + float startAng = i % 2 == 0 ? rand(-5, 0) : rand(0, 5); + + ascent(i in 0..num){ + ascent(k in 0..dense){ + int bullet = CreateShotA1(ObjMove_GetX(ship), ObjMove_GetY(ship), FUNC_LERP_LINEAR(spd, spd, i/num), startAng + k * 360/dense + dir * i * 4, KEV_BALL_ORANGE, 5+i); + _BulletRescale(bullet, 0.6, true, 0.25); + _Delay(bullet, 5+i*2); + } + } + + Shoot1; + wait(del); + i++; + + } + +} + +function WaveGround4(){ + + int del = FUNC_LERP_DECEL(WG4_bulletDelayMax, WG4_bulletDelayMin, rank/RANK_MAX); + int num = FUNC_LERP_DECEL(WG4_enmNumMin, WG4_enmNumMax, rank/RANK_MAX); + float enmspd = rand(baseMoveSpeedH * (1 + MoveSpeedRankMultiplierL*rank), baseMoveSpeedVH * (1 + MoveSpeedRankMultiplierL*rank)); + float spd = FUNC_LERP_DECEL(WG4_bulletSpdMin, WG4_bulletSpdMax, rank/RANK_MAX); + int time = FUNC_LERP_DECEL(WG4_invinTimeMax, WG4_invinTimeMin, rank/RANK_MAX); + float bushspd = baseMoveSpeedVL * (1 + MoveSpeedRankMultiplierVL*rank); + + float x = 0, y = 0; + + int bussy = _CreateDangerBush( + 34, time, + STG_WIDTH/2, -128, bushspd + ); + + async{ + + wait(time/2); + + while(!Obj_IsDeleted(bussy)){ + x = ObjMove_GetX(bussy); + y = ObjMove_GetY(bussy); + yield; + } + + if( + (y > STG_HEIGHT+64) + ) + { + return; + } + // Release bussy busses + + loop(num){ + + int enm = _SmallFairy( + 38, time/2, + x, y + ); + + int debris = _CreateBushRemnant( + 35, time/2, + x, y + ); + + enmPattern(enm); + enmPattern2(debris); + + } + + task enmPattern(int ID){ + + float valueX = clamp([rand(-enmspd*1, -enmspd*0.25), rand(enmspd*0.25, enmspd*1)][rand_int(0, 1)], -12, 12); + float valueY = -enmspd * rand(1, 1.5); + + ObjMove_AddPatternB2(ID, 0, valueX, valueY, -valueX/45, -valueY/45, valueX/20, -valueY/1.25); + + while(!Obj_IsDeleted(ID) && ObjMove_GetY(ID) > 0 && ObjMove_GetY(ID) < STG_HEIGHT * 7/8){ + + if (ObjMove_GetSpeedY(ID) <= -valueY/24) {ObjEnemy_SetDamageRate(ID, 0, 0);} + else {ObjEnemy_SetDamageRate(ID, 100, 100);} + + ObjMove_SetY(ID, clamp(ObjMove_GetY(ID), 0, STG_HEIGHT+99999999)); + + int bullet = CreateShotA1(ObjMove_GetX(ID), ObjMove_GetY(ID), spd, GetAngleToPlayer(ID), KEV_BALL_LAVENDER, 5); + + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 5); + Shoot1; + + wait(del); + } + } + + task enmPattern2(int ID){ + + float valueX = clamp([rand(-enmspd*1.25, -enmspd*0.75), rand(enmspd*1.25, enmspd*0.75)][rand_int(0, 1)], -12, 12); + float valueY = -enmspd * rand(1, 1.5); + + ObjMove_AddPatternB2(ID, 0, valueX, valueY, -valueX/35, -valueY/35, valueX/12.5, -valueY); + //ObjRender_SetAlpha(ID, 160); + + while(!Obj_IsDeleted(ID)){ + + if (ObjMove_GetSpeedY(ID) <= -valueY/24) {ObjEnemy_SetDamageRate(ID, 0, 0);} + else {ObjEnemy_SetDamageRate(ID, 100, 100);} + + ObjMove_SetY(ID, clamp(ObjMove_GetY(ID), 0, STG_HEIGHT+99999999)); + + ObjRender_SetAngleZ(ID, ObjRender_GetAngleZ(ID)+3); + + yield; + + } + + } + + } + + wait(time/2); + + while(length(enmGround) > 0){yield;} + + return; +} + +function WaveGround5(){ + + float speedMove = baseMoveSpeedVL * (1 + MoveSpeedRankMultiplierVL * rank) * 0.5; + + int num = FUNC_LERP_DECEL(WG5_bulletNumMin, WG5_bulletNumMax, rank/RANK_MAX); + int del = FUNC_LERP_DECEL(WG5_bulletDelayMax, WG5_bulletDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_DECEL(WG5_bulletSpdMin, WG5_bulletSpdMax, rank/RANK_MAX); + float[] moveX = [[180, -1.5], [0, 1.5]][GetCommonData("Flying Loops Cleared", 0) % 2]; + + int ship = _CreateDecker( + 37, del*3, + playerX, -180, speedMove + ); + + async{ + if(GetCommonData("Rush", false) == true){WaveGround3();} + else{} + } + + async{ + + while(!Obj_IsDeleted(ship)){ + + ObjMove_SetSpeedY(ship, speedMove); + ObjMove_SetX(ship, STG_WIDTH/2 + STG_WIDTH/2 * cos(moveX[0])); + + if (ObjMove_GetY(ship) <= 0) {ObjEnemy_SetDamageRate(ship, 0, 0);} + else if (ObjMove_GetY(ship) <= FUNC_LERP_LINEAR(180, 60, rank/RANK_MAX)) {ObjEnemy_SetDamageRate(ship, 25, 0);} + else {ObjEnemy_SetDamageRate(ship, 100, 100);} + + moveX[0] += moveX[1]; + + yield; + + } + + } + + int i = 0; + float startAng = 0; + + while(!Obj_IsDeleted(ship)){ + + int x = i % 2 == 0 ? 64 : -64; + + ascent(i in 0..num){ + int bullet = CreateShotA1(ObjMove_GetX(ship)+x, ObjMove_GetY(ship)+160, FUNC_LERP_LINEAR(spd, spd*1.5, i/num), 90, KEV_LEAF_ORANGE, 5); + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 10); + ObjShot_SetDelayMotionEnable(bullet, true); + } + + Shoot1; + wait(del); + i++; + + } + +} + +function WaveGround6(){ + + SetCommonData("Rush", true); + + WaveGround5(); + + SetCommonData("Rush", false); + +} + +*/ + +function Wave1(){ + + int num = FUNC_LERP_ACCEL(W1_fairyNumMin, W1_fairyNumMax, rank/RANK_MAX); + int decel = FUNC_LERP_ACCEL(W1_decelTimeMax, W1_decelTimeMin, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(W1_bulletDelayMax, W1_bulletDelayMin, rank/RANK_MAX); + int spawndel = FUNC_LERP_ACCEL(W1_spawnDelayMax, W1_spawnDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W1_bulletSpdMin, W1_bulletSpdMax, rank/RANK_MAX); + float movespd = baseMoveSpeedH * (1 + MoveSpeedRankMultiplierL*rank); + + task CreateEnemyA(float startY){ + + int enm = _SmallFairy( + 40, decel+del*2, + GetStgFrameWidth()+128, startY + ); + + ObjMove_AddPatternA2(enm, 0, movespd*2, 180, -movespd*2/decel, 0, 0); + ObjMove_AddPatternA2(enm, decel, NO_CHANGE, NO_CHANGE, movespd/decel, movespd, 0); + + wait(decel); + + while(!Obj_IsDeleted(enm) && ObjMove_GetX(enm) > STG_WIDTH * 1/8){ + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), spd, GetAngleToPlayer(enm), KEV_BALL_PURPLE, 5); + + _Delay(bullet, 5); + Shoot1; + + wait(del); + + } + + } + + ascent(i in 1..6){ + + CreateEnemyA(i * STG_HEIGHT/6); + + if(i != 6){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + ascent(i in 1..6){ + + CreateEnemyA((6-i) * STG_HEIGHT/6); + + if(i != 6){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; + +} + +function Wave2(){ + + int num = FUNC_LERP_ACCEL(W2_fairyNumMin, W2_fairyNumMax, rank/RANK_MAX); + int bulletnum = FUNC_LERP_ACCEL(W2_bulletfanNumMin, W2_bulletfanNumMax, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(W2_bulletDelayMax, W2_bulletDelayMin, rank/RANK_MAX); + int spawndel = FUNC_LERP_ACCEL(W2_spawnDelayMax, W2_spawnDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W2_bulletSpdMin, W2_bulletSpdMax, rank/RANK_MAX); + float movespd = baseMoveSpeedM * (1 + MoveSpeedRankMultiplierL*rank); + float range = FUNC_LERP_ACCEL(W2_rangeMin, W2_rangeMax, rank/RANK_MAX); + float[] spdrange = [-4, 4]; + + task CreateEnemyA(float startX, float startY, float angMove){ + + float ang = 180; + + int enm = _Spirit( + 40, del, startX, startY + ); + + async{ + + while(!Obj_IsDeleted(enm)){ + + //ObjMove_SetSpeed(enm, ) + ObjMove_AddPatternB1(enm, 0, -movespd, sin(ang) * spdrange[1]); + ang += 3.5; + yield; + + } + + } + + async{ + + wait(spawndel); + + while(!Obj_IsDeleted(enm) & ObjMove_GetX(enm) > STG_WIDTH * 1/8){ + + int bullet = CreateFan + ( + enm, bulletnum, KEV_FIRESMALL_AQUA, 1, + 0, range, spd, spd/1.5, 1, + 0, 0, + PATTERN_FAN_AIMED, false + ); + + //_Delay(bullet, 5); + Shoot1; + + wait(del); + + } + + } + + } + + ascent(i in 0..num){ + + float y = playerY; + + y = clamp(y, STG_HEIGHT * 1/5, STG_HEIGHT * 4/5); + CreateEnemyA(STG_WIDTH+128, y, 0); + + if(i != num){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + ascent(i in 0..num){ + + float y = playerY; + + y = clamp(y, STG_HEIGHT * 1/5, STG_HEIGHT * 4/5); + CreateEnemyA(STG_WIDTH+128, y, 0); + + if(i != num){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; +} + + +function Wave3(){ + + int num = FUNC_LERP_ACCEL(W3_fairyNumMin, W3_fairyNumMax, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(W3_bulletDelayMax, W3_bulletDelayMin, rank/RANK_MAX); + int bulletnum = FUNC_LERP_ACCEL(W3_bulletfanNumMin, W3_bulletfanNumMax, rank/RANK_MAX); + int spawndel = FUNC_LERP_ACCEL(W3_spawnDelayMax, W3_spawnDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W3_bulletSpdMin, W3_bulletSpdMax, rank/RANK_MAX); + float movespd = baseMoveSpeedH * (1 + MoveSpeedRankMultiplierL*rank); + float range = FUNC_LERP_ACCEL(W3_rangeMin, W3_rangeMax, rank/RANK_MAX); + float[] rangemove = [2.5, 4]; + int counter = 1; + + task CreateEnemyA(float startX, float startY, float spd){ + + float ang = rand(0, 180); + float spdMax = rand(rangemove[0], rangemove[1]); + + int enm = _MushroomFairy( + 40, del*3, + startX, startY + ); + + async{ + + while(!Obj_IsDeleted(enm)){ + + //ObjMove_SetSpeed(enm, ) + + ObjMove_AddPatternB1(enm, 0, sin(ang) * spdMax, spd); + ang += 3; + yield; + + } + + } + + async{ + + while(!Obj_IsDeleted(enm)){ + + if(ObjMove_GetY(enm) > STG_HEIGHT+128 || ObjMove_GetY(enm) < -128){ + Obj_Delete(enm); + break; + } + + if(ObjMove_GetY(enm) < STG_HEIGHT && ObjMove_GetY(enm) > 0){ + + if (spd < 0){ + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), spd, GetAngleToPlayer(enm)+180, KEV_FIRELARGE_PURPLE, 10); + ObjRender_SetAngleZ(bullet, 180); + _Delay(bullet, 10); + + } + + else{ + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), spd, GetAngleToPlayer(enm), KEV_FIRELARGE_PURPLE, 10); + _Delay(bullet, 10); + + } + //_Delay(bullet, 5); + Shoot1; + + } + + wait(del); + + + } + + } + + } + + ascent(i in 0..num){ + + CreateEnemyA(rand(STG_WIDTH*6/8, STG_WIDTH*7/8), counter >= 1 ? -128 : STG_HEIGHT+128, movespd*counter); + + counter *= -1; + + if(i != num){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; + +} + +function Wave4(){ + + int num = FUNC_LERP_ACCEL(W4_fairyNumMin, W4_fairyNumMax, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(W4_bulletDelayMax, W4_bulletDelayMin, rank/RANK_MAX); + int bulletnum = FUNC_LERP_ACCEL(W4_bulletNumMin, W4_bulletNumMax, rank/RANK_MAX); + int spawndel = FUNC_LERP_ACCEL(W4_spawnDelayMax, W4_spawnDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W4_bulletSpdMin, W4_bulletSpdMax, rank/RANK_MAX); + float movespd = baseMoveSpeedH * (1 + MoveSpeedRankMultiplierL*rank); + int stoptime = FUNC_LERP_LINEAR(W4_stopTimeMax, W4_stopTimeMin, rank/RANK_MAX); + + int counter = 1; + + task CreateEnemyA(float startX, float startY, float angle){ + + int enm = _MushroomFairyAlt( + 40, del*3, + startX, startY + ); + + ObjMove_AddPatternA1(enm, 0, movespd, rand(angle-5, angle+5)); + ObjMove_SetAngularVelocity(enm, rand(-0.1, 0.1)); + + async{ + + while(!Obj_IsDeleted(enm)){ + + if(ObjMove_GetY(enm) > STG_HEIGHT+128 || ObjMove_GetY(enm) < -128){ + Obj_Delete(enm); + break; + } + + yield; + + } + + } + + async{ + + while(!Obj_IsDeleted(enm)){ + + if(ObjMove_GetY(enm) < STG_HEIGHT && ObjMove_GetY(enm) > 0){ + + ascent(i in 0..bulletnum){ + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), 0, 180, KEV_FIRESMALL_AQUA, 10); + //ObjRender_SetAngleZ(bullet, 180); + _Delay(bullet, 10); + + ObjMove_AddPatternA2(bullet, stoptime, NO_CHANGE, NO_CHANGE, spd/stoptime, spd, 0); + + Shoot1; + wait(del); + + } + + } + + wait(del*3); + + } + + } + + } + + ascent(i in 0..num){ + + CreateEnemyA(rand(STG_WIDTH*6.5/8, STG_WIDTH*7/8), counter >= 1 ? -128 : STG_HEIGHT+128, counter >= 1 ? 90 : 270); + + counter *= -1; + + if(i != num){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; + +} + +function Wave5(){ + + int num = FUNC_LERP_LINEAR(W5_fairyNumMin, W5_fairyNumMax, rank/RANK_MAX); + int spawndel = FUNC_LERP_ACCEL(W4_spawnDelayMax, W4_spawnDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W4_bulletSpdMin, W4_bulletSpdMax, rank/RANK_MAX); + float movetime = FUNC_LERP_LINEAR(W5_moveTimeMin, W5_moveTimeMax, rank/RANK_MAX); + float movespeed = FUNC_LERP_LINEAR(16, 18, rank/RANK_MAX); + + task CreateEnemyA(float startX, float startY, float movespeed){ + + int enm = _SmallFairy( + 40, 30, + startX, startY + ); + + ObjEnemy_SetDamageRate(enm, 0, 0); + ObjMove_AddPatternB2(enm, 0, 0, movespeed, 0, -movespeed/movetime, 0, -movespeed); + + async{ + + while(!Obj_IsDeleted(enm)){ + + if(ObjMove_GetY(enm) > STG_HEIGHT+128 || ObjMove_GetY(enm) < -128){ + Obj_Delete(enm); + break; + } + + yield; + + } + + } + + async{ + + wait(movetime); + ObjEnemy_SetDamageRate(enm, 100, 100); + + if(!Obj_IsDeleted(enm)){ + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), spd, GetAngleToPlayer(enm), KEV_BALL_PURPLE, 5); + Shoot1; + _Delay(bullet, 5); + } + + } + + } + + float x = rand(STG_WIDTH*4/7, STG_WIDTH*5.25/7); + + ascent(k in 0..num){ + CreateEnemyA(x + k * 84, -96, movespeed); + } + + wait(spawndel); + + x = rand(STG_WIDTH*4/7, STG_WIDTH*5/7); + + ascent(k in 0..num){ + CreateEnemyA(x + k * 84, STG_HEIGHT+96, -movespeed); + } + + while(length(enmFly) > 1){yield;} + + return; + +} + +function WaveGround1(){ + + int dense = FUNC_LERP_LINEAR(WG1_ringDenseMin, WG1_ringDenseMax, rank/RANK_MAX); + float spd = FUNC_LERP_LINEAR(WG1_bulletSpdMin, WG1_bulletSpdMax, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(WG1_bulletDelayMax, WG1_bulletDelayMin, rank/RANK_MAX); + float movespd = baseMoveSpeedM * (1 + MoveSpeedRankMultiplierL*rank); + + task CreateEnemyA(float startX, float startY, float angle){ + + int enm = _MushroomFairyAlt( + 36, del*3, + startX, startY + ); + + ObjMove_AddPatternA1(enm, 0, movespd, 180); + + async{ + + while(!Obj_IsDeleted(enm)){ + + if(ObjMove_GetY(enm) > STG_HEIGHT+128 || ObjMove_GetY(enm) < -128 || ObjMove_GetX(enm) < -128 || ObjMove_GetX(enm) > STG_WIDTH+128){ + Obj_Delete(enm); + break; + } + + yield; + + } + + } + + async{ + + while(!Obj_IsDeleted(enm)){ + + float ang = rand(0, 360); + + if(ObjMove_GetY(enm) < STG_HEIGHT && ObjMove_GetY(enm) > 0){ + + ascent(i in 0..dense){ + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), spd, ang + i * 360/dense, KEV_FIRESMALL_AQUA, 10); + //ObjRender_SetAngleZ(bullet, 180); + _Delay(bullet, 10); + + Shoot2; + + } + + } + + wait(del); + + } + + } + + } + + if(rank <= 5){ + CreateEnemyA(STG_WIDTH+128, STG_HEIGHT * 1/5, 180); + CreateEnemyA(STG_WIDTH+128, STG_HEIGHT * 4/5, 180); + } + + else{ + CreateEnemyA(STG_WIDTH+128, STG_HEIGHT * 1/5, 180); + CreateEnemyA(STG_WIDTH+128, STG_HEIGHT * 1/2, 180); + CreateEnemyA(STG_WIDTH+128, STG_HEIGHT * 4/5, 180); + } + + while(length(enmGround) > 1){yield;} + +} + +function WaveGround2(float pos){ + + float speedMove = baseMoveSpeed1L * (1 + MoveSpeedRankMultiplierL * rank); + + int dense = FUNC_LERP_DECEL(WG2_spiralDenseMin, WG2_spiralDenseMax, rank/RANK_MAX); + int num = FUNC_LERP_DECEL(WG2_spiralNumMin, WG2_spiralNumMax, rank/RANK_MAX); + int del = FUNC_LERP_DECEL(WG2_spiralDelayMax, WG2_spiralDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_DECEL(WG2_spiralSpdMin, WG2_spiralSpdMax, rank/RANK_MAX); + float k = pos; + + k = clamp(k, STG_HEIGHT * 1/5, STG_HEIGHT * 4/5); + + int ship = _YukiOnna( + 36, del*3, + STG_WIDTH+128, k + ); + + ObjMove_AddPatternA1(ship, 0, speedMove, 180); + + async{ + + while(!Obj_IsDeleted(ship)){ + + if (ObjMove_GetX(ship) <= 0) {ObjEnemy_SetDamageRate(ship, 0, 0);} + else if (ObjMove_GetX(ship) <= FUNC_LERP_LINEAR(STG_WIDTH-240, STG_WIDTH-120, rank/RANK_MAX)) + {ObjEnemy_SetDamageRate(ship, 40, 40);} + else {ObjEnemy_SetDamageRate(ship, 100, 100);} + + yield; + + } + + } + + int i = 0; + float startAng = 0; + + while(!Obj_IsDeleted(ship)){ + + int dir = i % 2 == 0 ? 1 : -1; + float startAng = i % 2 == 0 ? rand(-5, 0) : rand(0, 5); + + ascent(i in 0..num){ + ascent(k in 0..dense){ + int bullet = CreateShotA1(ObjMove_GetX(ship), ObjMove_GetY(ship), FUNC_LERP_LINEAR(spd, spd, i/num), startAng + k * 360/dense + dir * i * 4, KEV_BALL_LAVENDER, 5+i); + _Delay(bullet, 5+i*2); + } + } + + Shoot2; + wait(del); + i++; + + } + +} + +/* + +function Wave3(){ + + int linenum = FUNC_LERP_LINEAR(W3_bulletLineNumMin, W3_bulletLineNumMax, rank/RANK_MAX); + int dense = FUNC_LERP_LINEAR(W3_bulletDenseMin, W3_bulletDenseMax, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(W3_bulletDelayMax, W3_bulletDelayMin, rank/RANK_MAX); + int zakodel = FUNC_LERP_ACCEL(W3_zakospawnDelayMax, W3_zakospawnDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W3_bulletSpdMin, W3_bulletSpdMax, rank/RANK_MAX); + float movespd = baseMoveSpeed1L * (1 + MoveSpeedRankMultiplierL*rank); + float zakomovespd = baseMoveSpeedVH * (1 + MoveSpeedRankMultiplierL*rank); + float angmovespd =FUNC_LERP_ACCEL(W3_angleMoveSpdMin, W3_angleMoveSpdMax, rank/RANK_MAX); + float startX = [0, STG_WIDTH][GetCommonData("Flying Loops Cleared", 0) % 2]; + float[] moveX = [[180, -angmovespd], [0, angmovespd]][GetCommonData("Flying Loops Cleared", 0) % 2]; + float angStart = rand(0, 360); + int i = 0; + + int enmLarge = _LargeDancer( + 40, 90, + startX, -144 + ); + + async{ + + while(!Obj_IsDeleted(enmLarge)){ + + ObjMove_SetSpeedY(enmLarge, movespd); + ObjMove_SetX(enmLarge, STG_WIDTH/2 + STG_WIDTH/2 * cos(moveX[0])); + + if (ObjMove_GetY(enmLarge) <= FUNC_LERP_LINEAR(144, 48, rank/RANK_MAX)) {ObjEnemy_SetDamageRate(enmLarge, 0, 0);} + else {ObjEnemy_SetDamageRate(enmLarge, 100, 100);} + + moveX[0] += moveX[1]; + + yield; + + } + + } + + while(!Obj_IsDeleted(enmLarge)){ + + int shot = CreateFan(enmLarge, 1, KEV_LEAF_LAVENDER, linenum, + angStart+i*1*360/dense, 0, spd/1.25, spd, + 0.75, + 0, 0, + PATTERN_FAN, false + ); + int shot2 = CreateFan(enmLarge, 1, KEV_LEAF_LAVENDER, linenum, + angStart+(180+angStart)+i*(-1)*360/dense, 0, spd/1.25, spd, + 0.75, + 0, 0, + PATTERN_FAN, false + ); + + Shoot2; + + i++; + wait(del); + + } + + // FUCK YOU HERE'S SOME ZAKO + + task CreateEnemyA(float startX){ + + int enm = _SmallFairy( + 39, zakomovespd*2, + startX, -64 + ); + + ObjMove_AddPatternA1(enm, 0, zakomovespd*1.5, atan2(playerY - (-64), playerX - startX)); + + async{ + while(!Obj_IsDeleted(enm)){ + if (ObjMove_GetY(enm) <= 64) {ObjEnemy_SetDamageRate(enm, 0, 0);} + else {ObjEnemy_SetDamageRate(enm, 400, 400);} + yield; + } + } + + while(!Obj_IsDeleted(enm) && ObjMove_GetY(enm) < STG_HEIGHT * 6/7){ + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), spd*1.2, GetAngleToPlayer(enm), KEV_BALL_LAVENDER, 5); + + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 5); + Shoot1; + + wait(del*10); + + } + + } + + ascent(i in 1..7){ + + CreateEnemyA(i * STG_WIDTH/7); + + if(i != 7){wait(zakodel);} + else{} + + } + + ascent(i in 1..7){ + + CreateEnemyA((7-i) * STG_WIDTH/7); + + if(i != 7){wait(zakodel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; + +} + +function Wave4(){ + + int del = FUNC_LERP_ACCEL(W4_bulletDelayMax, W4_bulletDelayMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W4_bulletSpdMin, W4_bulletSpdMax, rank/RANK_MAX); + int spawndel = FUNC_LERP_ACCEL(W4_spawnDelayMax, W4_spawnDelayMin, rank/RANK_MAX); + int invin = FUNC_LERP_ACCEL(W4_invinTimeMax, W4_invinTimeMin, rank/RANK_MAX); + float movespd = baseMoveSpeedH * (1 + MoveSpeedRankMultiplierVL*rank); + + task CreateEnemyA(float startX){ + + int enm = _Oni( + 41, invin, + startX, -128 + ); + + ObjMove_AddPatternA1(enm, 0, movespd, 90); + + while(!Obj_IsDeleted(enm) && ObjMove_GetY(enm) < STG_HEIGHT * 4/5){ + + if (ObjMove_GetY(enm) <= 128) {ObjEnemy_SetDamageRate(enm, 0, 0);} + else {ObjEnemy_SetDamageRate(enm, 100, 100);} + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), spd, GetAngleToPlayer(enm), KEV_FIRE_PINK, 5); + + _BulletRescale(bullet, 1, true, 1); + _Delay(bullet, 5); + Shoot2; + + wait(del); + + } + + } + + ascent(i in 1..6){ + + CreateEnemyA(1.5*STG_WIDTH/8 + 96); + CreateEnemyA(1.5*STG_WIDTH/8 - 96); + + if(i != 6){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + ascent(i in 1..6){ + + CreateEnemyA(6.5*STG_WIDTH/8 - 96); + CreateEnemyA(6.5*STG_WIDTH/8 + 96); + + if(i != 6){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; + + +} + +function Wave5(){ + + float acceltime = FUNC_LERP_ACCEL(W5_accelTimeMax, W5_accelTimeMin, rank/RANK_MAX); + float bulletwait = FUNC_LERP_ACCEL(W5_bulletWaitTimeMax, W5_bulletWaitTimeMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W5_bulletSpdMin, W5_bulletSpdMax, rank/RANK_MAX); + float angrange = FUNC_LERP_ACCEL(W5_angRangeMin, W5_angRangeMax, rank/RANK_MAX); + float del = FUNC_LERP_ACCEL(W5_bulletDelayMax, W5_bulletDelayMin, rank/RANK_MAX); + float spawndel = FUNC_LERP_ACCEL(W4_spawnDelayMax, W4_spawnDelayMin, rank/RANK_MAX); + float movespd = min(baseMoveSpeedVH * (1 + MoveSpeedRankMultiplierH * rank) * 1.2, 18); + + task CreateEnemyA(float startX){ + + float angMove = atan2(playerY - (-96), playerX - startX); + + int enm = _SmallWitch( + 40, del*20, + startX, -96 + ); + + ObjMove_AddPatternA1(enm, 0, movespd, angMove); + ObjRender_SetAngleZ(enm, angMove); + + while(!Obj_IsDeleted(enm) && ObjMove_GetY(enm) < STG_HEIGHT * 1/2){ + + if (ObjMove_GetY(enm) <= 128) {ObjEnemy_SetDamageRate(enm, 0, 0);} + else {ObjEnemy_SetDamageRate(enm, 100, 100);} + + int bullet = CreateShotA1(ObjMove_GetX(enm), ObjMove_GetY(enm), 0, angMove+rand(-angrange, angrange), KEV_LEAF_PINK, 5); + + _BulletRescale(bullet, 0.75, true, 1); + _Delay(bullet, 5); + + ObjMove_AddPatternA2(bullet, bulletwait, NO_CHANGE, NO_CHANGE, spd/acceltime, spd, 0); + + wait(del); + + } + + } + + ChargeSFX; + + ascent(i in 1..7){ + + CreateEnemyA(i * STG_WIDTH/7); + + if(i != 7){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + ChargeSFX; + + ascent(i in 1..7){ + + CreateEnemyA((7-i) * STG_WIDTH/7); + + if(i != 7){wait(spawndel);} + else{} + + } + + while(length(enmFly) > 1){yield;} + + return; + +} + +function Wave6(){ + + int dense = FUNC_LERP_LINEAR(W6_spiralDenseMin, W6_spiralDenseMax, rank/RANK_MAX); + int del = FUNC_LERP_ACCEL(W6_bulletDelayMax, W6_bulletDelayMin, rank/RANK_MAX); + int zakodel = FUNC_LERP_ACCEL(W6_zakospawnDelayMax, W6_zakospawnDelayMin, rank/RANK_MAX); + int waittime = FUNC_LERP_ACCEL(W6_bulletWaitTimeMax, W6_bulletWaitTimeMin, rank/RANK_MAX); + float spd = FUNC_LERP_ACCEL(W6_bulletSpdMin, W6_bulletSpdMax, rank/RANK_MAX); + float angoff = FUNC_LERP_ACCEL(W6_spiralAngOffsetMax, W6_spiralAngOffsetMin, rank/RANK_MAX); + float movespd = baseMoveSpeedM * (1 + MoveSpeedRankMultiplierL*rank); + float zakomovespd = baseMoveSpeedVH * (1 + MoveSpeedRankMultiplierL*rank); + float space = FUNC_LERP_ACCEL(W6_angRangeMin, W6_angRangeMax, rank/RANK_MAX); + int bulletnum = FUNC_LERP_LINEAR(W6_bulletNumMin, W6_bulletNumMax, rank/RANK_MAX); + float angStart = rand(0, 360); + int i = 0; + + int enmLarge = _LargeWitch( + 40, 90, + playerX, -144 + ); + + async{ + + ObjMove_AddPatternA1(enmLarge, 0, movespd, 90); + + while(!Obj_IsDeleted(enmLarge)){ + + if (ObjMove_GetY(enmLarge) <= FUNC_LERP_LINEAR(144, 48, rank/RANK_MAX)) {ObjEnemy_SetDamageRate(enmLarge, 15, 15);} + else {ObjEnemy_SetDamageRate(enmLarge, 100, 100);} + + yield; + + } + + } + + while(!Obj_IsDeleted(enmLarge) && ObjMove_GetY(enmLarge) <= STG_HEIGHT * 7/8){ + + ascent(i in 0..dense){ + + int bullet = CreateShotA1(ObjMove_GetX(enmLarge) + 64 * cos(angStart + i * 360/dense), ObjMove_GetY(enmLarge) + 64 * sin(angStart + i * 360/dense), 0, angStart + i * 360/dense, KEV_LEAF_PINK, 5); + + _BulletRescale(bullet, 0.75, true, 0.25); + _Delay(bullet, 5); + ObjMove_AddPatternA2(bullet, waittime, NO_CHANGE, NO_CHANGE, spd/waittime, spd, 0); + + } + + angStart += angoff; + + Shoot2; + + wait(del); + + } + + task CreateEnemyA(float startX){ + + float time = waittime/2; + + int enm = _Oni( + 39, waittime*1.5, + startX, -64 + ); + + ObjEnemy_SetDamageRate(enm, 0, 0); + ObjMove_SetDestAtFrame(enm, startX, STG_HEIGHT * 1/8, time, LERP_DECELERATE); + + wait(time-1); + + ObjMove_AddPatternA2(enm, time, NO_CHANGE, 90, zakomovespd/waittime, zakomovespd, 0); + + async{ + while(!Obj_IsDeleted(enm)){ + if (ObjMove_GetY(enm) <= 0) {ObjEnemy_SetDamageRate(enm, 0, 0);} + else {ObjEnemy_SetDamageRate(enm, 200, 200);} + yield; + } + } + + while(!Obj_IsDeleted(enm) && ObjMove_GetY(enm) < STG_HEIGHT * 6/7){ + + CreateFan( + enm, bulletnum, KEV_FIRE_PINK, 1, + GetAngleToPlayer(enm), space, spd*1.25, spd*1.25/1.5, 1, + 0, 0, + PATTERN_FAN, false + ); + + wait(del*999); + + } + + } + + ascent(i in 1..8){ + + CreateEnemyA(i * STG_WIDTH/8); + + } + + wait(waittime/2); + + while(length(enmFly) > 1){yield;} + + return; + +} + +*/ +task _EndShake(shaketime, intensity){ + + float baseintensity = intensity; + float shakeno = shaketime; + + ascent(i in 0..shakeno){ + Set2DCameraFocusX(GetStgFrameWidth/2 + rand(-intensity, intensity)); + Set2DCameraFocusY(GetStgFrameHeight/2 + rand(-intensity, intensity)); + intensity = Interpolate_Decelerate(0, baseintensity, 1-i/shakeno); + shaketime--; + yield; + } + + while(shaketime > 0){yield;} + + Set2DCameraFocusX(GetStgFrameWidth/2); + Set2DCameraFocusY(GetStgFrameHeight/2); + yield; +} + +task _ObjShake(objID, shaketime, intensity){ + + float baseX = ObjMove_GetX(objID); + float baseY = ObjMove_GetY(objID); + float baseintensity = intensity; + float shakeno = shaketime; + + ascent(i in 0..shakeno){ + ObjMove_SetPosition(objID, baseX + rand(-intensity, intensity), baseY + rand(-intensity, intensity)/2); + intensity = Interpolate_Decelerate(0, baseintensity, 1-i/shakeno); + shaketime--; + yield; + } + + while(shaketime > 0){yield;} + + ObjMove_SetPosition(objID, baseX, baseY); + + yield; +} + + + diff --git a/script/Jam10/PackageLib/Img.png b/script/Jam10/PackageLib/Img.png new file mode 100644 index 0000000..2366925 Binary files /dev/null and b/script/Jam10/PackageLib/Img.png differ diff --git a/script/Jam10/PackageLib/MusicTitle.mp3 b/script/Jam10/PackageLib/MusicTitle.mp3 new file mode 100644 index 0000000..3e82aff Binary files /dev/null and b/script/Jam10/PackageLib/MusicTitle.mp3 differ diff --git a/script/Jam10/PackageLib/NarumiSTG_Manual.png b/script/Jam10/PackageLib/NarumiSTG_Manual.png new file mode 100644 index 0000000..f2d86a6 Binary files /dev/null and b/script/Jam10/PackageLib/NarumiSTG_Manual.png differ diff --git a/script/Jam10/Stage_Background.dnh b/script/Jam10/Stage_Background.dnh new file mode 100644 index 0000000..eb38625 --- /dev/null +++ b/script/Jam10/Stage_Background.dnh @@ -0,0 +1,113 @@ +let bossBG = "script/Jam10/resourceLib/Jam10_BG.png"; +let soundWarn = ObjSound_Create(); +let alphaMax = 255*((GetAreaCommonData("Config", "BGOpacity", 100))/100); +let exVol = GetAreaCommonData("Config", "SEVol", 100) * 0.01; + +//ObjSound_Load(sound, "script/game/resourceLib/dialogueblip.wav"); +ObjSound_Load(soundWarn, "script/game/resourceLib/warnSound.wav"); +//ObjSound_SetVolumeRate(sound, 100 * blipVol); +ObjSound_SetVolumeRate(soundWarn, 100 * blipVol); +//ObjSound_SetSoundDivision(sound, SOUND_SE); +ObjSound_SetSoundDivision(soundWarn, SOUND_SE); + +//LoadSound("script/game/StageLib/dialogueblip.wav"); + +LoadTextureEx(bossBG, true, true); + +function _ScrollBackground(){ + + int BossImg = _Create2DImage(bossBG, [0, 0, 640*4, 720]); + ObjRender_SetScaleXYZ(BossImg, 1); + ObjRender_SetPosition(BossImg, STG_WIDTH/2, STG_HEIGHT/2, 1); + Obj_SetRenderPriorityI(BossImg, 24); + + float scrollSpeed = 0; + float maxscrollSpeed = 14; + int curScroll = 0; + + async{ + loop{ + maxscrollSpeed = 9+GetCommonData("Rank", 1)*1.25; + wait(60); + } + } + + async{ + + loop{ + + //ObjSprite2D_SetDestRect(BossImg, 0, 0, STG_WIDTH/2, STG_HEIGHT/2); + ObjSprite2D_SetSourceRect(BossImg, curScroll, 0, curScroll+640*4, 720); + curScroll += scrollSpeed; + + scrollSpeed = min(maxscrollSpeed, scrollSpeed+0.05); + yield; + + } + + } + + ascent(i in 0..90){ + ObjRender_SetAlpha(BossImg, Interpolate_Decelerate(0, alphaMax, i/90)); + yield; + } + + NotifyEventAll(EV_START_MUSIC, 0); + + //Dialogue(); + //ObjRender_SetAlpha(BossImg, 255*((GetAreaCommonData("Config", "BGOpacity", 100))/100)); + +} + +function Dialogue(){ + + //ObjSound_Play(soundWarn); + + wait(30); + + int objText3 = CreateTextObject( + + STG_WIDTH/2, STG_HEIGHT/3-60, 80, + " ", "Origami Mommy", + 0x72CBFF, 0x72CBFF, + 0x08007C, 10, + 71 + + ); + + int objText = CreateTextObject( + + STG_WIDTH/2, STG_HEIGHT/2-60, 36, + " ", "Origami Mommy", + 0x72CBFF, 0x72CBFF, + 0x08007C, 6, + 71 + + ); + + int objText2 = CreateTextObject( + + STG_WIDTH/2, STG_HEIGHT/2, 36, + " ", "Origami Mommy", + 0x72CBFF, 0x72CBFF, + 0x08007C, 6, + 71 + + ); + + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER); + ObjText_SetHorizontalAlignment(objText2, ALIGNMENT_CENTER); + ObjText_SetHorizontalAlignment(objText3, ALIGNMENT_CENTER); + + TTextScroll(objText3, "GET READY!"); + TTextScroll(objText, "IN 99 SECONDS"); + //wait(60); + TTextScroll(objText2, "BECOME THE STRONGEST!"); + + wait(60); + + Obj_Delete(objText); + Obj_Delete(objText2); + Obj_Delete(objText3); + +} diff --git a/script/Jam10/resourceLib/BossTheme.mp3 b/script/Jam10/resourceLib/BossTheme.mp3 new file mode 100644 index 0000000..173b8da Binary files /dev/null and b/script/Jam10/resourceLib/BossTheme.mp3 differ diff --git a/script/Jam10/resourceLib/Jam10.png b/script/Jam10/resourceLib/Jam10.png new file mode 100644 index 0000000..df70a52 Binary files /dev/null and b/script/Jam10/resourceLib/Jam10.png differ diff --git a/script/Jam10/resourceLib/Jam10_BG.png b/script/Jam10/resourceLib/Jam10_BG.png new file mode 100644 index 0000000..ccb73b6 Binary files /dev/null and b/script/Jam10/resourceLib/Jam10_BG.png differ diff --git a/script/Jam10/resourceLib/Spritesheet_StationJam.png b/script/Jam10/resourceLib/Spritesheet_StationJam.png new file mode 100644 index 0000000..bd831e1 Binary files /dev/null and b/script/Jam10/resourceLib/Spritesheet_StationJam.png differ diff --git a/script/Jam10/resourceLib/StageTheme.mp3 b/script/Jam10/resourceLib/StageTheme.mp3 new file mode 100644 index 0000000..e28050c Binary files /dev/null and b/script/Jam10/resourceLib/StageTheme.mp3 differ diff --git a/script/KevinSound/RaspberryTickle_Giggle.wav b/script/KevinSound/RaspberryTickle_Giggle.wav new file mode 100644 index 0000000..ddb450d Binary files /dev/null and b/script/KevinSound/RaspberryTickle_Giggle.wav differ diff --git a/script/KevinSound/bfxr_Charge.wav b/script/KevinSound/bfxr_Charge.wav new file mode 100644 index 0000000..4189ad1 Binary files /dev/null and b/script/KevinSound/bfxr_Charge.wav differ diff --git a/script/KevinSound/bfxr_EnemyBoom.wav b/script/KevinSound/bfxr_EnemyBoom.wav new file mode 100644 index 0000000..e642deb Binary files /dev/null and b/script/KevinSound/bfxr_EnemyBoom.wav differ diff --git a/script/KevinSound/bfxr_ExtendLegacy.wav b/script/KevinSound/bfxr_ExtendLegacy.wav new file mode 100644 index 0000000..1b3c22e Binary files /dev/null and b/script/KevinSound/bfxr_ExtendLegacy.wav differ diff --git a/script/KevinSound/bfxr_Pause.wav b/script/KevinSound/bfxr_Pause.wav new file mode 100644 index 0000000..5d4c354 Binary files /dev/null and b/script/KevinSound/bfxr_Pause.wav differ diff --git a/script/KevinSound/bfxr_PlayerFire1.wav b/script/KevinSound/bfxr_PlayerFire1.wav new file mode 100644 index 0000000..f5406bf Binary files /dev/null and b/script/KevinSound/bfxr_PlayerFire1.wav differ diff --git a/script/KevinSound/bfxr_RinnoBomb.wav b/script/KevinSound/bfxr_RinnoBomb.wav new file mode 100644 index 0000000..00d3b5b Binary files /dev/null and b/script/KevinSound/bfxr_RinnoBomb.wav differ diff --git a/script/KevinSound/bfxr_Select.wav b/script/KevinSound/bfxr_Select.wav new file mode 100644 index 0000000..2159021 Binary files /dev/null and b/script/KevinSound/bfxr_Select.wav differ diff --git a/script/KevinSound/bfxr_Shoot1.wav b/script/KevinSound/bfxr_Shoot1.wav new file mode 100644 index 0000000..cb0d724 Binary files /dev/null and b/script/KevinSound/bfxr_Shoot1.wav differ diff --git a/script/KevinSound/bfxr_Shoot2.wav b/script/KevinSound/bfxr_Shoot2.wav new file mode 100644 index 0000000..e6b7c32 Binary files /dev/null and b/script/KevinSound/bfxr_Shoot2.wav differ diff --git a/script/KevinSound/bossBoom.wav b/script/KevinSound/bossBoom.wav new file mode 100644 index 0000000..4a7bc66 Binary files /dev/null and b/script/KevinSound/bossBoom.wav differ diff --git a/script/KevinSystem/Default_Background_IceMountain.txt b/script/KevinSystem/Default_Background_IceMountain.txt new file mode 100644 index 0000000..96074eb Binary files /dev/null and b/script/KevinSystem/Default_Background_IceMountain.txt differ diff --git a/script/KevinSystem/Default_Effect.txt b/script/KevinSystem/Default_Effect.txt new file mode 100644 index 0000000..bd0f0d3 Binary files /dev/null and b/script/KevinSystem/Default_Effect.txt differ diff --git a/script/KevinSystem/Default_EndScene.txt b/script/KevinSystem/Default_EndScene.txt new file mode 100644 index 0000000..1656d86 Binary files /dev/null and b/script/KevinSystem/Default_EndScene.txt differ diff --git a/script/KevinSystem/Default_Pause.txt b/script/KevinSystem/Default_Pause.txt new file mode 100644 index 0000000..38222f6 Binary files /dev/null and b/script/KevinSystem/Default_Pause.txt differ diff --git a/script/KevinSystem/Default_ReplaySaveScene.txt b/script/KevinSystem/Default_ReplaySaveScene.txt new file mode 100644 index 0000000..73a97ec Binary files /dev/null and b/script/KevinSystem/Default_ReplaySaveScene.txt differ diff --git a/script/KevinSystem/Default_ShotConst.txt b/script/KevinSystem/Default_ShotConst.txt new file mode 100644 index 0000000..00b50a9 Binary files /dev/null and b/script/KevinSystem/Default_ShotConst.txt differ diff --git a/script/KevinSystem/Default_ShotData.txt b/script/KevinSystem/Default_ShotData.txt new file mode 100644 index 0000000..ac117e2 Binary files /dev/null and b/script/KevinSystem/Default_ShotData.txt differ diff --git a/script/KevinSystem/Default_System_MagicCircle.txt b/script/KevinSystem/Default_System_MagicCircle.txt new file mode 100644 index 0000000..a25a0c3 Binary files /dev/null and b/script/KevinSystem/Default_System_MagicCircle.txt differ diff --git a/script/KevinSystem/GeneralSoundLib.txt b/script/KevinSystem/GeneralSoundLib.txt new file mode 100644 index 0000000..507071c --- /dev/null +++ b/script/KevinSystem/GeneralSoundLib.txt @@ -0,0 +1,120 @@ +// Sound effects for boss go here. + +let lib = GetModuleDirectory() ~ "./script/KevinSystem/RyannSFX/ryannlib/"; +let libKev = "script/KevinSound/"; + +let SFXVol = GetAreaCommonData("Config", "SEVol", 100) * 0.01; + +// Sound paths + +let defeatsnd = lib ~ "../bossdie.wav"; +let lw = lib ~ "sp_lastword.wav"; + +let bullet1 = libKev ~ "bfxr_Shoot1.wav"; // Regular bullet sound +let bullet2 = libKev ~ "bfxr_Shoot2.wav"; // Shiny bullet sound + +let bullet3 = lib ~ "se_explode.wav"; +let lightning1 = lib ~ "se_don00.wav"; // Lightning sound 1/Explosion sound +let lightning2 = lib ~ "se_kira02.wav"; // Lightning sound 2 +let laze = lib ~ "se_lazer01.wav"; // Laser sound +let lazeB = lib ~ "se_lazer00.wav"; +let slash = lib ~ "se_slash.ogg"; + +let pause = libKev ~ "bfxr_Pause.wav"; +let chargeA = libKev ~ "bfxr_Charge.wav"; + +let selection = libKev ~ "se_select00.wav"; +let thunder = lib ~ "se_boon00.wav"; // Thunder/delay laser sound +let bomb = lib ~ "se_nep00.wav"; + +let extend = libKev ~ "bfxr_ExtendLegacy.wav"; // Clear game! + +let lenenwarn = lib ~ "../lenenwarning.wav"; +let chargeB = lib ~ "se_ch01.wav"; + +// Sound objects declarations + +let warnsfx = ObjSound_Create(); +let lwmusic = ObjSound_Create(); +let fire1 = ObjSound_Create(); +let fire2 = ObjSound_Create(); +let fire3 = ObjSound_Create(); +let light1 = ObjSound_Create(); +let light2 = ObjSound_Create(); +let laser = ObjSound_Create(); +let laserB = ObjSound_Create(); +let charge = ObjSound_Create(); +let phase = ObjSound_Create(); +let grz = ObjSound_Create(); +let swing = ObjSound_Create(); +let pausesfx = ObjSound_Create(); +let choose = ObjSound_Create(); +let thundersfx = ObjSound_Create(); +let bombsfx = ObjSound_Create(); +let extendsfx = ObjSound_Create(); +let icebreak = ObjSound_Create(); +let entrance = ObjSound_Create(); + +int sfxBoom = ObjSound_Create(); +int bossBoom = ObjSound_Create(); +int bossLaugh = ObjSound_Create(); + +// Merge function that loads sounds and significantly decreases volume +// so the ears do not die from SFX overload. + +function LoadEx(targetobj, targetpath, targetvol){ + + ObjSound_Load(targetobj, targetpath); + ObjSound_SetVolumeRate(targetobj, targetvol * SFXVol); + ObjSound_SetSoundDivision(targetobj, SOUND_SE); +} + +task _SoundTask{ + + //LoadEx(lwmusic, lw, 80); + LoadEx(fire1, bullet1, 65); + LoadEx(fire2, bullet2, 65); + LoadEx(pausesfx, pause, 40); + LoadEx(extendsfx, extend, 60); + + LoadEx(light1, lightning1, 20); + LoadEx(light2, lightning2, 20); + LoadEx(laser, laze, 20); + LoadEx(laserB, lazeB, 20); + //LoadEx(grz, graze, 20); + LoadEx(swing, slash, 20); + + LoadEx(choose, selection, 30); + LoadEx(thundersfx, thunder, 25); + LoadEx(charge, chargeA, 75); + LoadEx(phase, chargeB, 75); + LoadEx(fire3, bullet3, 35); + LoadEx(bombsfx, bomb, 50); + + LoadEx(warnsfx, lenenwarn, 30); + LoadEx(icebreak, lib ~ "se_don00.wav", 60); + LoadEx(entrance, lib ~ "se_gun00.wav", 60); + + LoadEx(sfxBoom, libKev ~ "bfxr_EnemyBoom.wav", 60); + LoadEx(bossBoom, libKev ~ "bossBoom.wav", 60); + LoadEx(bossLaugh, libKev ~ "RaspberryTickle_Giggle.wav", 60); +} + +// Functions to load sounds in scripts + +task Shoot1{ObjSound_Play(fire1); return;} +task Shoot2{ObjSound_Play(fire2); return;} +task Shoot3{ObjSound_Play(fire3); return;} +task Lit1{ObjSound_Play(light1); return;} +task Lit2{ObjSound_Play(light2); return;} +task GrazeSFX{ObjSound_Play(grz); return;} +task SwordSlashSFX{ObjSound_Play(swing); return;} +task PauseGameSFX{ObjSound_Play(pausesfx); return;} +task SelectOptionSFX{ObjSound_Play(choose); return;} +task LaserSFX{ObjSound_Play(laser); return;} +task LaserBSFX{ObjSound_Play(laserB); return;} +task ThunderSFX{ObjSound_Play(thundersfx); return;} +task ChargeSFX{ObjSound_Play(charge); return;} +task ChargeBreakSFX{ObjSound_Play(phase); return;} +task BombSFX{ObjSound_Play(bombsfx); return;} +task ExtendSFX{ObjSound_Play(extendsfx); return;} \ No newline at end of file diff --git a/script/KevinSystem/Init.dnh b/script/KevinSystem/Init.dnh new file mode 100644 index 0000000..9eccce7 --- /dev/null +++ b/script/KevinSystem/Init.dnh @@ -0,0 +1,22 @@ + +if(IsCommonDataAreaExists("PIV") == false){ + CreateCommonDataArea("PIV"); + SetAreaCommonData("PIV", "currentvalue", 10000); + SetAreaCommonData("PIV", "ChainAmount", 1); +} +else{} + +if(IsCommonDataAreaExists("ScriptID") == false){ + CreateCommonDataArea("ScriptID"); + SetAreaCommonData("ScriptID", "SystemID", 0); + SetAreaCommonData("ScriptID", "ItemID", 0); +} +else{} + +if(IsCommonDataAreaExists("ChainChecks") == false){ + CreateCommonDataArea("ChainChecks"); + SetAreaCommonData("ChainChecks", "IsChaining", false); +} +else{} + + \ No newline at end of file diff --git a/script/KevinSystem/KevinShot/KevinShot_Alt_HD.png b/script/KevinSystem/KevinShot/KevinShot_Alt_HD.png new file mode 100644 index 0000000..32f5a79 Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_Alt_HD.png differ diff --git a/script/KevinSystem/KevinShot/KevinShot_Alt_HD_2.png b/script/KevinSystem/KevinShot/KevinShot_Alt_HD_2.png new file mode 100644 index 0000000..a93ea0c Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_Alt_HD_2.png differ diff --git a/script/KevinSystem/KevinShot/KevinShot_Alt_HD_Fireball.png b/script/KevinSystem/KevinShot/KevinShot_Alt_HD_Fireball.png new file mode 100644 index 0000000..7f98693 Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_Alt_HD_Fireball.png differ diff --git a/script/KevinSystem/KevinShot/KevinShot_Alt_HD_Fireball_Inv.png b/script/KevinSystem/KevinShot/KevinShot_Alt_HD_Fireball_Inv.png new file mode 100644 index 0000000..aff883b Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_Alt_HD_Fireball_Inv.png differ diff --git a/script/KevinSystem/KevinShot/KevinShot_Alt_HD_Inv.png b/script/KevinSystem/KevinShot/KevinShot_Alt_HD_Inv.png new file mode 100644 index 0000000..6aee6d9 Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_Alt_HD_Inv.png differ diff --git a/script/KevinSystem/KevinShot/KevinShot_FireballPxEdit.ase b/script/KevinSystem/KevinShot/KevinShot_FireballPxEdit.ase new file mode 100644 index 0000000..93a72c4 Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_FireballPxEdit.ase differ diff --git a/script/KevinSystem/KevinShot/KevinShot_PxEdit.ase b/script/KevinSystem/KevinShot/KevinShot_PxEdit.ase new file mode 100644 index 0000000..6c65457 Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_PxEdit.ase differ diff --git a/script/KevinSystem/KevinShot/KevinShot_PxEdit_A.png b/script/KevinSystem/KevinShot/KevinShot_PxEdit_A.png new file mode 100644 index 0000000..4e4004d Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_PxEdit_A.png differ diff --git a/script/KevinSystem/KevinShot/KevinShot_PxEdit_B.png b/script/KevinSystem/KevinShot/KevinShot_PxEdit_B.png new file mode 100644 index 0000000..8388e9b Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_PxEdit_B.png differ diff --git a/script/KevinSystem/KevinShot/KevinShot_PxEdit_C.png b/script/KevinSystem/KevinShot/KevinShot_PxEdit_C.png new file mode 100644 index 0000000..bc66e15 Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_PxEdit_C.png differ diff --git a/script/KevinSystem/KevinShot/KevinShot_PxEdit_D.png b/script/KevinSystem/KevinShot/KevinShot_PxEdit_D.png new file mode 100644 index 0000000..7cd3f4a Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_PxEdit_D.png differ diff --git a/script/KevinSystem/KevinShot/misc.txt b/script/KevinSystem/KevinShot/misc.txt new file mode 100644 index 0000000..8dd8c0e --- /dev/null +++ b/script/KevinSystem/KevinShot/misc.txt @@ -0,0 +1,33 @@ +/* +For Danmakufu users. + +These functions are meant to be used alongside my pastel shotsheet due to the very high native resolution. +*/ + +// Bullet rescaling task, also has functionality for setting a new hitbox size relative to the new bullet graphic size. I highly recommend leaving hitboxscale to true. + +task _BulletRescale(target, float scale, bool hitboxscale, hitboxlevel){ + + ObjRender_SetScaleXYZ(target, scale, scale, 1); + + if (hitboxscale){ + ObjShot_SetIntersectionScaleXY(target, scale*hitboxlevel, scale*hitboxlevel); // Note the formula. The hitbox will have been scaled accordingly along with the bullet graphic, but you can use hitboxlevel to adjust the scale further. + return; + } + + else{return;} + +} + +// Delay task, provided by Naudiz (@Naudogs). For best effects, ensure destscale is equal to the resized scale of the bullet graphic, and orgscale be larger than it. + +task _Delay(target, del, orgscale, destscale, orgalpha, destalpha){ + + ObjShot_SetDelay(target, del); + ObjShot_SetDelayGraphic(target, ObjShot_GetImageID(target)); // unless you already have the ID in the function somewhere, in which case you can just use that, or use any other graphic + ObjShot_SetDelayMode(target, DELAY_LERP, LERP_ACCELERATE, LERP_DECELERATE); // delay mode, scale lerp, alpha lerp. Check ph3sx's New Functions Documentation.txt for more details. + ObjShot_SetDelayScaleParameter(target, destscale, orgscale, del); // lerps from orgscale to destscale scale in del frames (use the value from ObjShot_SetDelay for del) + ObjShot_SetDelayAlphaParameter(target, destalpha, orgalpha, del); // lerps from orgalpha to destalpha scale in del frames (use the value from ObjShot_SetDelay for del) + return; + +} \ No newline at end of file diff --git a/script/KevinSystem/KevinShot/readme.txt b/script/KevinSystem/KevinShot/readme.txt new file mode 100644 index 0000000..29850da --- /dev/null +++ b/script/KevinSystem/KevinShot/readme.txt @@ -0,0 +1,28 @@ +Kevin's Ultra HD/4K Pastel Shotsheet + +0.10a + +-------- + +Thank you for downloading and using my pastel shotsheet! + +This shotsheet features various common bullet types in a variety of "pastel" colors - colors lighter than your usual bullet graphics, but they should hopefully still be just as visible nonetheless. It has a *very* big native resolution (the first sheet is 4096x4096, with each bullet graphic being 256x256), and therefore is meant to be used with a similarly large game resolution and/or bullet rescaling functions. (See misc.txt for information regarding the latter in Danmakufu). It comes pre-packed with shot data and shot constant sheets meant for instant use in Danmakufu. + +The shotsheet is still heavily incomplete. In the works is a second sheet (4096x2048) featuring more bullet types (fireballs, lasers, bubbles), some changes to existing bullet graphics to improve aesthetic and visibility, and half-size versions for regular HD reoslutions. + +How to use: + +Extract the directory to an appropriate location in your project and to load them, just include the shot constant text file in your script file (shotconst_4K.txt). +-------- +The shot sheet images can be used in other engines as well. However it is the responsibility of the user to port the shot sheet data themselves. + +The shot sheet images are free to use NON-COMMERCIALLY. Please credit me (Kevinmonitor/Kevin Mink) fully! + +You are free to modify the shot sheets. Please state so if you do so however (for example, in the credits for your project you put a "modified by the author with permission" next to my attribution). + +Please do not redistribute these shotsheets on your own. +-------- +CONTACT: + +Discord: Kevinmonitor#6745 +Twitter: @kevinminh_alt diff --git a/script/KevinSystem/KevinShot/shotconst_HD.txt b/script/KevinSystem/KevinShot/shotconst_HD.txt new file mode 100644 index 0000000..f924fc9 --- /dev/null +++ b/script/KevinSystem/KevinShot/shotconst_HD.txt @@ -0,0 +1,142 @@ + +local +{ + LoadTextureEx(GetCurrentScriptDirectory ~ "./KevinShot_Alt_HD.png", true, true); + LoadTextureEx(GetCurrentScriptDirectory ~ "./KevinShot_Alt_HD_Fireball.png", true, true); + LoadTextureEx(GetCurrentScriptDirectory ~ "./KevinShot_Alt_HD_Inv.png", true, true); + LoadTextureEx(GetCurrentScriptDirectory ~ "./KevinShot_Alt_HD_Fireball_Inv.png", true, true); + LoadEnemyShotData(GetCurrentScriptDirectory ~ "shotdata_HD.txt"); + LoadEnemyShotData(GetCurrentScriptDirectory ~ "shotdata_HD_2.txt"); + LoadEnemyShotData(GetCurrentScriptDirectory ~ "shotdata_HD_3.txt"); + LoadEnemyShotData(GetCurrentScriptDirectory ~ "shotdata_HD_4.txt"); +} + +const KEV_BALL_RED = 2000; +const KEV_BALL_ORANGE = 2001; +const KEV_BALL_YELLOW = 2002; +const KEV_BALL_GREEN = 2003; +const KEV_BALL_AQUA = 2004; +const KEV_BALL_LAVENDER = 2005; +const KEV_BALL_PURPLE = 2006; +const KEV_BALL_PINK = 2007; +const KEV_BALL_WHITE = 2008; + +const KEV_FIRESMALL_RED = 2011; +const KEV_FIRESMALL_ORANGE = 2012; +const KEV_FIRESMALL_YELLOW = 2013; +const KEV_FIRESMALL_GREEN = 2014; +const KEV_FIRESMALL_AQUA = 2015; +const KEV_FIRESMALL_LAVENDER = 2016; +const KEV_FIRESMALL_PURPLE = 2017; +const KEV_FIRESMALL_PINK = 2018; +const KEV_FIRESMALL_WHITE = 2019; + +const KEV_LEAF_RED = 2022; +const KEV_LEAF_ORANGE = 2023; +const KEV_LEAF_YELLOW = 2024; +const KEV_LEAF_GREEN = 2025; +const KEV_LEAF_AQUA = 2026; +const KEV_LEAF_LAVENDER = 2027; +const KEV_LEAF_PURPLE = 2028; +const KEV_LEAF_PINK = 2029; +const KEV_LEAF_WHITE = 2030; + +const KEV_FIRELARGE_RED = 2033; +const KEV_FIRELARGE_ORANGE = 2034; +const KEV_FIRELARGE_YELLOW = 2035; +const KEV_FIRELARGE_GREEN = 2036; +const KEV_FIRELARGE_AQUA = 2037; +const KEV_FIRELARGE_LAVENDER = 2038; +const KEV_FIRELARGE_PURPLE = 2039; +const KEV_FIRELARGE_PINK = 2040; +const KEV_FIRELARGE_WHITE = 2041; + +const KEV_ARROW_RED = 2044; +const KEV_ARROW_ORANGE = 2045; +const KEV_ARROW_YELLOW = 2046; +const KEV_ARROW_GREEN = 2047; +const KEV_ARROW_AQUA = 2048; +const KEV_ARROW_LAVENDER = 2049; +const KEV_ARROW_PURPLE = 2050; +const KEV_ARROW_PINK = 2051; +const KEV_ARROW_WHITE = 2052; + +const KEV_BUTTERFLY_RED = 2055; +const KEV_BUTTERFLY_ORANGE = 2056; +const KEV_BUTTERFLY_YELLOW = 2057; +const KEV_BUTTERFLY_GREEN = 2058; +const KEV_BUTTERFLY_AQUA = 2059; +const KEV_BUTTERFLY_LAVENDER = 2060; +const KEV_BUTTERFLY_PURPLE = 2061; +const KEV_BUTTERFLY_PINK = 2062; +const KEV_BUTTERFLY_WHITE = 2063; + +const KEV_AURABALL_RED = 2066; +const KEV_AURABALL_ORANGE = 2067; +const KEV_AURABALL_YELLOW = 2068; +const KEV_AURABALL_GREEN = 2069; +const KEV_AURABALL_AQUA = 2070; +const KEV_AURABALL_LAVENDER = 2071; +const KEV_AURABALL_PURPLE = 2072; +const KEV_AURABALL_PINK = 2073; +const KEV_AURABALL_WHITE = 2074; + +const KEV_FIRE_RED = 2075; +const KEV_FIRE_ORANGE = 2076; +const KEV_FIRE_YELLOW = 2077; +const KEV_FIRE_GREEN = 2078; +const KEV_FIRE_AQUA = 2079; +const KEV_FIRE_LAVENDER = 2080; +const KEV_FIRE_PURPLE = 2081; +const KEV_FIRE_PINK = 2082; +const KEV_FIRE_WHITE = 2083; + +const KEV_BUBBLE_RED = 2086; +const KEV_BUBBLE_ORANGE = 2087; +const KEV_BUBBLE_YELLOW = 2088; +const KEV_BUBBLE_GREEN = 2089; +const KEV_BUBBLE_AQUA = 2090; +const KEV_BUBBLE_LAVENDER = 2091; +const KEV_BUBBLE_PURPLE = 2092; +const KEV_BUBBLE_PINK = 2093; + +const KEV_KNIFE_RED = 2096; +const KEV_KNIFE_ORANGE = 2097; +const KEV_KNIFE_YELLOW = 2098; +const KEV_KNIFE_GREEN = 2099; +const KEV_KNIFE_AQUA = 2100; +const KEV_KNIFE_LAVENDER = 2101; +const KEV_KNIFE_PURPLE = 2102; +const KEV_KNIFE_PINK = 2103; + +const KEV_BITCHKILLER_ARROW = 3000; + +// Inverted colours + +const KEV_BALL_RED_INV = 2200; const KEV_PEOPLE_RED_INV = 2211; const KEV_LEAF_RED_INV = 2222; const KEV_AMULET_RED_INV = 2233; const KEV_ARROW_RED_INV = 2244; const KEV_BUTTERFLY_RED_INV = 2255; const KEV_AURABALL_RED_INV = 2266; const KEV_BUBBLE_RED_INV = 2286; const KEV_KNIFE_RED_INV = 2296; + +const KEV_BALL_ORANGE_INV = 2201; const KEV_PEOPLE_ORANGE_INV = 2212; const KEV_LEAF_ORANGE_INV = 2223; const KEV_AMULET_ORANGE_INV = 2234; const KEV_ARROW_ORANGE_INV = 2245; const KEV_BUTTERFLY_ORANGE_INV = 2256; const KEV_AURABALL_ORANGE_INV = 2267; const KEV_BUBBLE_ORANGE_INV = 2287; const KEV_KNIFE_ORANGE_INV = 2297; + +const KEV_BALL_YELLOW_INV = 2202; const KEV_PEOPLE_YELLOW_INV = 2213; const KEV_LEAF_YELLOW_INV = 2224; const KEV_AMULET_YELLOW_INV = 2235; const KEV_ARROW_YELLOW_INV = 2246; const KEV_BUTTERFLY_YELLOW_INV = 2257; const KEV_AURABALL_YELLOW_INV = 2268; const KEV_BUBBLE_YELLOW_INV = 2288; const KEV_KNIFE_YELLOW_INV = 2298; + +const KEV_BALL_GREEN_INV = 2203; const KEV_PEOPLE_GREEN_INV = 2214; const KEV_LEAF_GREEN_INV = 2225; const KEV_AMULET_GREEN_INV = 2236; const KEV_ARROW_GREEN_INV = 2247; const KEV_BUTTERFLY_GREEN_INV = 2258; const KEV_AURABALL_GREEN_INV = 2269; const KEV_BUBBLE_GREEN_INV = 2289; const KEV_KNIFE_GREEN_INV = 2299; + +const KEV_BALL_AQUA_INV = 2204; const KEV_PEOPLE_AQUA_INV = 2215; const KEV_LEAF_AQUA_INV = 2226; const KEV_AMULET_AQUA_INV = 2237; const KEV_ARROW_AQUA_INV = 2248; const KEV_BUTTERFLY_AQUA_INV = 2259; const KEV_AURABALL_AQUA_INV = 2270; const KEV_BUBBLE_AQUA_INV = 2290; const KEV_KNIFE_AQUA_INV = 2300; + +const KEV_BALL_LAVENDER_INV = 2205; const KEV_PEOPLE_LAVENDER_INV = 2216; const KEV_LEAF_LAVENDER_INV = 2227; const KEV_AMULET_LAVENDER_INV = 2238; const KEV_ARROW_LAVENDER_INV = 2249; const KEV_BUTTERFLY_LAVENDER_INV = 2260; const KEV_AURABALL_LAVENDER_INV = 2271; const KEV_BUBBLE_LAVENDER_INV = 2291; const KEV_KNIFE_LAVENDER_INV = 2301; + +const KEV_BALL_PURPLE_INV = 2206; const KEV_PEOPLE_PURPLE_INV = 2217; const KEV_LEAF_PURPLE_INV = 2228; const KEV_AMULET_PURPLE_INV = 2239; const KEV_ARROW_PURPLE_INV = 2250; const KEV_BUTTERFLY_PURPLE_INV = 2261; const KEV_AURABALL_PURPLE_INV = 2272; const KEV_BUBBLE_PURPLE_INV = 2292; const KEV_KNIFE_PURPLE_INV = 2302; + +const KEV_BALL_PINK_INV = 2207; const KEV_PEOPLE_PINK_INV = 2218; const KEV_LEAF_PINK_INV = 2229; const KEV_AMULET_PINK_INV = 2240; const KEV_ARROW_PINK_INV = 2251; const KEV_BUTTERFLY_PINK_INV = 2262; const KEV_AURABALL_PINK_INV = 2273; const KEV_BUBBLE_PINK_INV = 2293; const KEV_KNIFE_PINK_INV = 2303; + +const KEV_BALL_WHITE_INV = 2208; const KEV_PEOPLE_WHITE_INV = 2219; const KEV_LEAF_WHITE_INV = 2230; const KEV_AMULET_WHITE_INV = 2241; const KEV_ARROW_WHITE_INV = 2252; const KEV_BUTTERFLY_WHITE_INV = 2263; const KEV_AURABALL_WHITE_INV = 2274; const KEV_BUBBLE_WHITE_INV = 2294; const KEV_KNIFE_WHITE_INV = 2304; + +const KEV_FIRE_RED_INV = 2275; +const KEV_FIRE_ORANGE_INV = 2276; +const KEV_FIRE_YELLOW_INV = 2277; +const KEV_FIRE_GREEN_INV = 2278; +const KEV_FIRE_AQUA_INV = 2279; +const KEV_FIRE_LAVENDER_INV = 2280; +const KEV_FIRE_PURPLE_INV = 2281; +const KEV_FIRE_PINK_INV = 2282; +const KEV_FIRE_WHITE_INV = 2283; diff --git a/script/KevinSystem/KevinShot/shotdata_HD.txt b/script/KevinSystem/KevinShot/shotdata_HD.txt new file mode 100644 index 0000000..f15b6cb --- /dev/null +++ b/script/KevinSystem/KevinShot/shotdata_HD.txt @@ -0,0 +1,108 @@ +#UserShotData + +shot_image = "./KevinShot_PxEdit_A.png" + +// BALL + +ShotData { id = 2000 rect = (0,0,128,128) collision = 12 delay_color = (255,255,255) angular_velocity = 5} //RED +ShotData { id = 2001 rect = (128,0,256,128) collision = 12 delay_color = (255,255,255) angular_velocity = 5} //ORANGE +ShotData { id = 2002 rect = (256,0,384,128) collision = 12 delay_color = (255,255,255) angular_velocity = 5} //YELLOW +ShotData { id = 2003 rect = (384,0,512,128) collision = 12 delay_color = (255,255,255) angular_velocity = 5} //GREEN +ShotData { id = 2004 rect = (512,0,640,128) collision = 12 delay_color = (255,255,255) angular_velocity = 5} //AQUA +ShotData { id = 2005 rect = (640,0,768,128) collision = 12 delay_color = (255,255,255) angular_velocity = 5} //LAVENDER +ShotData { id = 2006 rect = (768,0,896,128) collision = 12 delay_color = (255,255,255) angular_velocity = 5} //PURPLE +ShotData { id = 2007 rect = (896,0,1024,128) collision = 12 delay_color = (255,255,255) angular_velocity = 5} //PINK +ShotData { id = 2008 rect = (1024,0,1152,128) collision = 12 delay_color = (255,255,255) angular_velocity = 5} //WHITE + +// FIRE SMALL + +ShotData { id = 2011 rect = (0,128,128,256) collision = (12,0,-8) delay_color = (255,255,255) } //RED +ShotData { id = 2012 rect = (128,128,256,256) collision = (12,0,-8) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2013 rect = (256,128,384,256) collision = (12,0,-8) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2014 rect = (384,128,512,256) collision = (12,0,-8) delay_color = (255,255,255) } //GREEN +ShotData { id = 2015 rect = (512,128,640,256) collision = (12,0,-8) delay_color = (255,255,255) } //AQUA +ShotData { id = 2016 rect = (640,128,768,256) collision = (12,0,-8) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2017 rect = (768,128,896,256) collision = (12,0,-8) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2018 rect = (896,128,1024,256) collision = (12,0,-8) delay_color = (255,255,255) } //PINK +ShotData { id = 2019 rect = (1024,128,1152,256) collision = (12,0,-8) delay_color = (255,255,255) } //WHITE + +// LEAF + +ShotData { id = 2022 rect = (0,256,128,384) collision = 8 delay_color = (255,255,255) } //RED +ShotData { id = 2023 rect = (128,256,256,384) collision = 8 delay_color = (255,255,255) } //ORANGE +ShotData { id = 2024 rect = (256,256,384,384) collision = 8 delay_color = (255,255,255) } //YELLOW +ShotData { id = 2025 rect = (384,256,512,384) collision = 8 delay_color = (255,255,255) } //GREEN +ShotData { id = 2026 rect = (512,256,640,384) collision = 8 delay_color = (255,255,255) } //AQUA +ShotData { id = 2027 rect = (640,256,768,384) collision = 8 delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2028 rect = (768,256,896,384) collision = 8 delay_color = (255,255,255) } //PURPLE +ShotData { id = 2029 rect = (896,256,1024,384) collision = 8 delay_color = (255,255,255) } //PINK +ShotData { id = 2030 rect = (1024,256,1152,384) collision = 8 delay_color = (255,255,255) } //WHITE + +// FIRE BIG + +ShotData { id = 2033 rect = (0,384,128,512) collision = (20,0,-12) delay_color = (255,255,255) } //RED +ShotData { id = 2034 rect = (128,384,256,512) collision = (20,0,-12) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2035 rect = (256,384,384,512) collision = (20,0,-12) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2036 rect = (384,384,512,512) collision = (20,0,-12) delay_color = (255,255,255) } //GREEN +ShotData { id = 2037 rect = (512,384,640,512) collision = (20,0,-12) delay_color = (255,255,255) } //AQUA +ShotData { id = 2038 rect = (640,384,768,512) collision = (20,0,-12) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2039 rect = (768,384,896,512) collision = (20,0,-12) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2040 rect = (896,384,1024,512) collision = (20,0,-12) delay_color = (255,255,255) } //PINK +ShotData { id = 2041 rect = (1024,384,1152,512) collision = (20,0,-12) delay_color = (255,255,255) } //WHITE + +ShotData { id = 2044 rect = (0,512,128,640) collision = (6,0,20) delay_color = (255,255,255) } //RED +ShotData { id = 2045 rect = (128,512,256,640) collision = (6,0,20) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2046 rect = (256,512,384,640) collision = (6,0,20) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2047 rect = (384,512,512,640) collision = (6,0,20) delay_color = (255,255,255) } //GREEN +ShotData { id = 2048 rect = (512,512,640,640) collision = (6,0,20) delay_color = (255,255,255) } //AQUA +ShotData { id = 2049 rect = (640,512,768,640) collision = (6,0,20) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2050 rect = (768,512,896,640) collision = (6,0,20) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2051 rect = (896,512,1024,640) collision = (6,0,20) delay_color = (255,255,255) } //PINK +ShotData { id = 2052 rect = (1024,512,1152,640) collision = (6,0,20) delay_color = (255,255,255) } //WHITE + +ShotData { id = 2055 rect = (0,640,128,768) collision = 12 delay_color = (255,255,255) } //RED +ShotData { id = 2056 rect = (128,640,256,768) collision = 12 delay_color = (255,255,255) } //ORANGE +ShotData { id = 2057 rect = (256,640,384,768) collision = 12 delay_color = (255,255,255) } //YELLOW +ShotData { id = 2058 rect = (384,640,512,768) collision = 12 delay_color = (255,255,255) } //GREEN +ShotData { id = 2059 rect = (512,640,640,768) collision = 12 delay_color = (255,255,255) } //AQUA +ShotData { id = 2060 rect = (640,640,768,768) collision = 12 delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2061 rect = (768,640,896,768) collision = 12 delay_color = (255,255,255) } //PURPLE +ShotData { id = 2062 rect = (896,640,1024,768) collision = 12 delay_color = (255,255,255) } //PINK +ShotData { id = 2063 rect = (1024,640,1152,768) collision = 12 delay_color = (255,255,255) } //WHITE + +ShotData { id = 2066 rect = (0,768,128,896) collision = 18 delay_color = (255,255,255) } //RED +ShotData { id = 2067 rect = (128,768,256,896) collision = 18 delay_color = (255,255,255) } //ORANGE +ShotData { id = 2068 rect = (256,768,384,896) collision = 18 delay_color = (255,255,255) } //YELLOW +ShotData { id = 2069 rect = (384,768,512,896) collision = 18 delay_color = (255,255,255) } //GREEN +ShotData { id = 2070 rect = (512,768,640,896) collision = 18 delay_color = (255,255,255) } //AQUA +ShotData { id = 2071 rect = (640,768,768,896) collision = 18 delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2072 rect = (768,768,896,896) collision = 18 delay_color = (255,255,255) } //PURPLE +ShotData { id = 2073 rect = (896,768,1024,896) collision = 18 delay_color = (255,255,255) } //PINK +ShotData { id = 2074 rect = (1024,768,1152,896) collision = 18 delay_color = (255,255,255) } //WHITE + +75 -> 83: fireballs + +ShotData { id = 2086 rect = (0,896,256,1152) collision = 48 delay_color = (255,255,255) } //RED +ShotData { id = 2087 rect = (256,896,512,1152) collision = 48 delay_color = (255,255,255) } //ORANGE +ShotData { id = 2088 rect = (512,896,768,1152) collision = 48 delay_color = (255,255,255) } //YELLOW +ShotData { id = 2089 rect = (768,896,1024,1152) collision = 48 delay_color = (255,255,255) } //GREEN +ShotData { id = 2090 rect = (1024,896,1280,1152) collision = 48 delay_color = (255,255,255) } //AQUA +ShotData { id = 2091 rect = (1280,896,1536,1152) collision = 48 delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2092 rect = (1536,896,1792,1152) collision = 48 delay_color = (255,255,255) } //PURPLE +ShotData { id = 2093 rect = (1792,896,2048,1152) collision = 48 delay_color = (255,255,255) } //PINK + +ShotData { id = 2096 rect = (0,1152,128,1280) collision = (8.5,0,-9.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (6.5,0,32.5) delay_color = (255,255,255) } //RED +ShotData { id = 2097 rect = (128,1152,256,1280) collision = (8.5,0,-9.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (6.5,0,32.5) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2098 rect = (256,1152,384,1280) collision = (8.5,0,-9.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (6.5,0,32.5) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2099 rect = (384,1152,512,1280) collision = (8.5,0,-9.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (6.5,0,32.5) delay_color = (255,255,255) } //GREEN +ShotData { id = 2100 rect = (512,1152,640,1280) collision = (8.5,0,-9.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (6.5,0,32.5) delay_color = (255,255,255) } //AQUA +ShotData { id = 2101 rect = (640,1152,768,1280) collision = (8.5,0,-9.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (6.5,0,32.5) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2102 rect = (768,1152,896,1280) collision = (8.5,0,-9.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (6.5,0,32.5) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2103 rect = (896,1152,1024,1280) collision = (8.5,0,-9.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (6.5,0,32.5) delay_color = (255,255,255) } //PINK +ShotData { id = 2104 rect = (1024,1152,1152,1280) collision = (8.5,0,-9.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (6.5,0,32.5) delay_color = (255,255,255) } //WHITE +ShotData { id = 2105 rect = (1152,1152,1280,1280) collision = (8.5,0,-9.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (6.5,0,32.5) delay_color = (255,255,255) } // +ShotData { id = 2106 rect = (1280,1152,1408,1280) collision = (8.5,0,-9.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (6.5,0,32.5) delay_color = (255,255,255) } // + + + + diff --git a/script/KevinSystem/KevinShot/shotdata_HD_2.txt b/script/KevinSystem/KevinShot/shotdata_HD_2.txt new file mode 100644 index 0000000..d89b879 --- /dev/null +++ b/script/KevinSystem/KevinShot/shotdata_HD_2.txt @@ -0,0 +1,24 @@ +#UserShotData + +shot_image = "./KevinShot_PxEdit_C.png" + +ShotData { id = 2075 AnimationData { animation_data = ( 6, 0, 0, 128, 128); animation_data = ( 6, 128, 0, 256, 128); animation_data = ( 6, 256, 0, 384, 128); animation_data = ( 6, 384, 0, 512, 128); } render = ALPHA collision = (13, 0, 24) delay_color = (255,255,255) } //RED +ShotData { id = 2076 AnimationData { animation_data = ( 6, 0, 128, 128, 256); animation_data = ( 6, 128, 128, 256, 256); animation_data = ( 6, 256, 128, 384, 256); animation_data = ( 6, 384, 128, 512, 256); } render = ALPHA collision = (13, 0, 24) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2077 AnimationData { animation_data = ( 6, 0, 256, 128, 384); animation_data = ( 6, 128, 256, 256, 384); animation_data = ( 6, 256, 256, 384, 384); animation_data = ( 6, 384, 256, 512, 384); } render = ALPHA collision = (13, 0, 24) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2078 AnimationData { animation_data = ( 6, 0, 384, 128, 512); animation_data = ( 6, 128, 384, 256, 512); animation_data = ( 6, 256, 384, 384, 512); animation_data = ( 6, 384, 384, 512, 512); } render = ALPHA collision = (13, 0, 24) delay_color = (255,255,255) } //GREEN +ShotData { id = 2079 AnimationData { animation_data = ( 6, 0, 512, 128, 640); animation_data = ( 6, 128, 512, 256, 640); animation_data = ( 6, 256, 512, 384, 640); animation_data = ( 6, 384, 512, 512, 640); } render = ALPHA collision = (13, 0, 24) delay_color = (255,255,255) } //AQUA +ShotData { id = 2080 AnimationData { animation_data = ( 6, 0, 640, 128, 768); animation_data = ( 6, 128, 640, 256, 768); animation_data = ( 6, 256, 640, 384, 768); animation_data = ( 6, 384, 640, 512, 768); } render = ALPHA collision = (13, 0, 24) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2081 AnimationData { animation_data = ( 6, 0, 768, 128, 896); animation_data = ( 6, 128, 768, 256, 896); animation_data = ( 6, 256, 768, 384, 896); animation_data = ( 6, 384, 768, 512, 896); } render = ALPHA collision = (13, 0, 24) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2082 AnimationData { animation_data = ( 6, 0, 896, 128, 1024); animation_data = ( 6, 128, 896, 256, 1024); animation_data = ( 6, 256, 896, 384, 1024); animation_data = ( 6, 384, 896, 512, 1024); } render = ALPHA collision = (13, 0, 24) delay_color = (255,255,255) } //PINK +ShotData { id = 2083 AnimationData { animation_data = ( 6, 0, 1024, 128, 1152); animation_data = ( 6, 128, 1024, 256, 1152); animation_data = ( 6, 256, 1024, 384, 1152); animation_data = ( 6, 384, 1024, 512, 1152); } render = ALPHA collision = (13, 0, 24) delay_color = (255,255,255) } //WHITE + +// Bitchkiller Arrow + +ShotData { + id = 3000 + rect = (1024, 0, 1536, 1280) + collision = (102, 0, 256) + collision = (50, 0, 352) + delay_color = (255, 255, 255) +} + diff --git a/script/KevinSystem/KevinShot/shotdata_HD_3.txt b/script/KevinSystem/KevinShot/shotdata_HD_3.txt new file mode 100644 index 0000000..aec42b9 --- /dev/null +++ b/script/KevinSystem/KevinShot/shotdata_HD_3.txt @@ -0,0 +1,103 @@ +#UserShotData + +// Inverted colors + +shot_image = "./KevinShot_PxEdit_B.png" + +ShotData { id = 2200 rect = (0,0,128,128) collision = 26 delay_color = (255,255,255) } //RED +ShotData { id = 2201 rect = (128,0,256,128) collision = 26 delay_color = (255,255,255) } //ORANGE +ShotData { id = 2202 rect = (256,0,384,128) collision = 26 delay_color = (255,255,255) } //YELLOW +ShotData { id = 2203 rect = (384,0,512,128) collision = 26 delay_color = (255,255,255) } //GREEN +ShotData { id = 2204 rect = (512,0,640,128) collision = 26 delay_color = (255,255,255) } //AQUA +ShotData { id = 2205 rect = (640,0,768,128) collision = 26 delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2206 rect = (768,0,896,128) collision = 26 delay_color = (255,255,255) } //PURPLE +ShotData { id = 2207 rect = (896,0,1024,128) collision = 26 delay_color = (255,255,255) } //PINK +ShotData { id = 2208 rect = (1024,0,1152,128) collision = 26 delay_color = (255,255,255) } //WHITE + +ShotData { id = 2211 rect = (0,128,128,256) collision = (17,0,7) delay_color = (255,255,255) } //RED +ShotData { id = 2212 rect = (128,128,256,256) collision = (17,0,7) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2213 rect = (256,128,384,256) collision = (17,0,7) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2214 rect = (384,128,512,256) collision = (17,0,7) delay_color = (255,255,255) } //GREEN +ShotData { id = 2215 rect = (512,128,640,256) collision = (17,0,7) delay_color = (255,255,255) } //AQUA +ShotData { id = 2216 rect = (640,128,768,256) collision = (17,0,7) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2217 rect = (768,128,896,256) collision = (17,0,7) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2218 rect = (896,128,1024,256) collision = (17,0,7) delay_color = (255,255,255) } //PINK +ShotData { id = 2219 rect = (1024,128,1152,256) collision = (17,0,7) delay_color = (255,255,255) } //WHITE + +ShotData { id = 2222 rect = (0,256,128,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //RED +ShotData { id = 2223 rect = (128,256,256,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2224 rect = (256,256,384,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2225 rect = (384,256,512,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //GREEN +ShotData { id = 2226 rect = (512,256,640,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //AQUA +ShotData { id = 2227 rect = (640,256,768,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2228 rect = (768,256,896,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2229 rect = (896,256,1024,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //PINK +ShotData { id = 2230 rect = (1024,256,1152,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //WHITE + +ShotData { id = 2233 rect = (0,384,256,512) collision = (28,0,0) delay_color = (255,255,255) } //RED +ShotData { id = 2234 rect = (128,384,256,512) collision = (28,0,0) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2235 rect = (256,384,384,512) collision = (28,0,0) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2236 rect = (384,384,512,512) collision = (28,0,0) delay_color = (255,255,255) } //GREEN +ShotData { id = 2237 rect = (512,384,640,512) collision = (28,0,0) delay_color = (255,255,255) } //AQUA +ShotData { id = 2238 rect = (640,384,768,512) collision = (28,0,0) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2239 rect = (768,384,896,512) collision = (28,0,0) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2240 rect = (896,384,1024,512) collision = (28,0,0) delay_color = (255,255,255) } //PINK +ShotData { id = 2241 rect = (1024,384,1152,512) collision = (28,0,0) delay_color = (255,255,255) } //WHITE + +ShotData { id = 2244 rect = (0,512,128,640) collision = (8,0,20) delay_color = (255,255,255) } //RED +ShotData { id = 2245 rect = (128,512,256,640) collision = (8,0,20) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2246 rect = (256,512,384,640) collision = (8,0,20) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2247 rect = (384,512,512,640) collision = (8,0,20) delay_color = (255,255,255) } //GREEN +ShotData { id = 2248 rect = (512,512,640,640) collision = (8,0,20) delay_color = (255,255,255) } //AQUA +ShotData { id = 2249 rect = (640,512,768,640) collision = (8,0,20) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2250 rect = (768,512,896,640) collision = (8,0,20) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2251 rect = (896,512,1024,640) collision = (8,0,20) delay_color = (255,255,255) } //PINK +ShotData { id = 2252 rect = (1024,512,1152,640) collision = (8,0,20) delay_color = (255,255,255) } //WHITE + +ShotData { id = 2255 rect = (0,640,128,768) collision = 12 delay_color = (255,255,255) } //RED +ShotData { id = 2256 rect = (128,640,256,768) collision = 12 delay_color = (255,255,255) } //ORANGE +ShotData { id = 2257 rect = (256,640,384,768) collision = 12 delay_color = (255,255,255) } //YELLOW +ShotData { id = 2258 rect = (384,640,512,768) collision = 12 delay_color = (255,255,255) } //GREEN +ShotData { id = 2259 rect = (512,640,640,768) collision = 12 delay_color = (255,255,255) } //AQUA +ShotData { id = 2260 rect = (640,640,768,768) collision = 12 delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2261 rect = (768,640,896,768) collision = 12 delay_color = (255,255,255) } //PURPLE +ShotData { id = 2262 rect = (896,640,1024,768) collision = 12 delay_color = (255,255,255) } //PINK +ShotData { id = 2263 rect = (1024,640,1152,768) collision = 12 delay_color = (255,255,255) } //WHITE + +ShotData { id = 2266 rect = (0,768,128,896) collision = 18 delay_color = (255,255,255) } //RED +ShotData { id = 2267 rect = (128,768,256,896) collision = 18 delay_color = (255,255,255) } //ORANGE +ShotData { id = 2268 rect = (256,768,384,896) collision = 18 delay_color = (255,255,255) } //YELLOW +ShotData { id = 2269 rect = (384,768,512,896) collision = 18 delay_color = (255,255,255) } //GREEN +ShotData { id = 2270 rect = (512,768,640,896) collision = 18 delay_color = (255,255,255) } //AQUA +ShotData { id = 2271 rect = (640,768,768,896) collision = 18 delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2272 rect = (768,768,896,896) collision = 18 delay_color = (255,255,255) } //PURPLE +ShotData { id = 2273 rect = (896,768,1024,896) collision = 18 delay_color = (255,255,255) } //PINK +ShotData { id = 2274 rect = (1024,768,1152,896) collision = 18 delay_color = (255,255,255) } //WHITE + +/* +75 -> 83: fireballs + +ShotData { id = 2086 rect = (0,896,256,1152) collision = 48 delay_color = (255,255,255) } //RED +ShotData { id = 2087 rect = (256,896,512,1152) collision = 48 delay_color = (255,255,255) } //ORANGE +ShotData { id = 2088 rect = (512,896,768,1152) collision = 48 delay_color = (255,255,255) } //YELLOW +ShotData { id = 2089 rect = (768,896,1024,1152) collision = 48 delay_color = (255,255,255) } //GREEN +ShotData { id = 2090 rect = (1024,896,1280,1152) collision = 48 delay_color = (255,255,255) } //AQUA +ShotData { id = 2091 rect = (1280,896,1536,1152) collision = 48 delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2092 rect = (1536,896,1792,1152) collision = 48 delay_color = (255,255,255) } //PURPLE +ShotData { id = 2093 rect = (1792,896,2048,1152) collision = 48 delay_color = (255,255,255) } //PINK +*/ + +ShotData { id = 2296 rect = (0,1152,128,1280) collision = (8.5,0,-5.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (7.5,0,32.5) delay_color = (255,255,255) } //RED +ShotData { id = 2097 rect = (128,1152,256,1280) collision = (8.5,0,-5.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (7.5,0,32.5) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2098 rect = (256,1152,384,1280) collision = (8.5,0,-5.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (7.5,0,32.5) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2099 rect = (384,1152,512,1280) collision = (8.5,0,-5.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (7.5,0,32.5) delay_color = (255,255,255) } //GREEN +ShotData { id = 2100 rect = (512,1152,640,1280) collision = (8.5,0,-5.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (7.5,0,32.5) delay_color = (255,255,255) } //AQUA +ShotData { id = 2101 rect = (640,1152,768,1280) collision = (8.5,0,-5.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (7.5,0,32.5) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2102 rect = (768,1152,896,1280) collision = (8.5,0,-5.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (7.5,0,32.5) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2103 rect = (896,1152,1024,1280) collision = (8.5,0,-5.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (7.5,0,32.5) delay_color = (255,255,255) } //PINK +ShotData { id = 2104 rect = (1024,1152,1152,1280) collision = (8.5,0,-5.5) collision = (8.5,0,6.5) collision = (8.5,0,19.5) collision = (7.5,0,32.5) delay_color = (255,255,255) } //WHITE + + + + + diff --git a/script/KevinSystem/KevinShot/shotdata_HD_4.txt b/script/KevinSystem/KevinShot/shotdata_HD_4.txt new file mode 100644 index 0000000..d1c8ef8 --- /dev/null +++ b/script/KevinSystem/KevinShot/shotdata_HD_4.txt @@ -0,0 +1,15 @@ +#UserShotData + +shot_image = "./KevinShot_Alt_HD_Fireball_Inv.png" + +ShotData { id = 2275 AnimationData { animation_data = ( 4, 0, 0, 128, 128); animation_data = ( 4, 128, 0, 256, 128); animation_data = ( 4, 256, 0, 384, 128); animation_data = ( 4, 384, 0, 512, 128); animation_data = ( 4, 512, 0, 640, 128); } render = ALPHA collision = 13 delay_color = (255,255,255) } //RED +ShotData { id = 2276 AnimationData { animation_data = ( 4, 0, 128, 128, 256); animation_data = ( 4, 128, 128, 256, 256); animation_data = ( 4, 256, 128, 384, 256); animation_data = ( 4, 384, 128, 512, 256); animation_data = ( 4, 512, 128, 640, 256); } render = ALPHA collision = 13 delay_color = (255,255,255) } //ORANGE +ShotData { id = 2277 AnimationData { animation_data = ( 4, 0, 256, 128, 384); animation_data = ( 4, 128, 256, 256, 384); animation_data = ( 4, 256, 256, 384, 384); animation_data = ( 4, 384, 256, 512, 384); animation_data = ( 4, 512, 256, 640, 384); } render = ALPHA collision = 13 delay_color = (255,255,255) } //YELLOW +ShotData { id = 2278 AnimationData { animation_data = ( 4, 0, 384, 128, 512); animation_data = ( 4, 128, 384, 256, 512); animation_data = ( 4, 256, 384, 384, 512); animation_data = ( 4, 384, 384, 512, 512); animation_data = ( 4, 512, 384, 640, 512); } render = ALPHA collision = 13 delay_color = (255,255,255) } //GREEN +ShotData { id = 2279 AnimationData { animation_data = ( 4, 0, 512, 128, 640); animation_data = ( 4, 128, 512, 256, 640); animation_data = ( 4, 256, 512, 384, 640); animation_data = ( 4, 384, 512, 512, 640); animation_data = ( 4, 512, 512, 640, 640); } render = ALPHA collision = 13 delay_color = (255,255,255) } //AQUA +ShotData { id = 2280 AnimationData { animation_data = ( 4, 0, 640, 128, 768); animation_data = ( 4, 128, 640, 256, 768); animation_data = ( 4, 256, 640, 384, 768); animation_data = ( 4, 384, 640, 512, 768); animation_data = ( 4, 512, 640, 640, 768); } render = ALPHA collision = 13 delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2281 AnimationData { animation_data = ( 4, 0, 768, 128, 896); animation_data = ( 4, 128, 768, 256, 896); animation_data = ( 4, 256, 768, 384, 896); animation_data = ( 4, 384, 768, 512, 896); animation_data = ( 4, 512, 768, 640, 896); } render = ALPHA collision = 13 delay_color = (255,255,255) } //PURPLE +ShotData { id = 2282 AnimationData { animation_data = ( 4, 0, 896, 128, 1024); animation_data = ( 4, 128, 896, 256, 1024); animation_data = ( 4, 256, 896, 384, 1024); animation_data = ( 4, 384, 896, 512, 1024); animation_data = ( 4, 512, 896, 640, 1024); } render = ALPHA collision = 13 delay_color = (255,255,255) } //PINK +ShotData { id = 2283 AnimationData { animation_data = ( 4, 0, 1024, 128, 1152); animation_data = ( 4, 128, 1024, 256, 1152); animation_data = ( 4, 256, 1024, 384, 1152); animation_data = ( 4, 384, 1024, 512, 1152); animation_data = ( 4, 512, 1024, 640, 1152); } render = ALPHA collision = 13 delay_color = (255,255,255) } //WHITE +ShotData { id = 2283 AnimationData { animation_data = ( 4, 0, 1024, 128, 1152); animation_data = ( 4, 128, 1024, 256, 1152); animation_data = ( 4, 256, 1024, 384, 1152); animation_data = ( 4, 384, 1024, 512, 1152); animation_data = ( 4, 512, 1024, 640, 1152); } render = ALPHA collision = 13 delay_color = (255,255,255) } //WHITE + diff --git a/script/KevinSystem/Kevin_PlayerLib.txt b/script/KevinSystem/Kevin_PlayerLib.txt new file mode 100644 index 0000000..fb61f00 --- /dev/null +++ b/script/KevinSystem/Kevin_PlayerLib.txt @@ -0,0 +1,829 @@ +/* -------------------------------------------------------------------- + + UNIVERSAL/GENERAL FUNCTIONS USED FOR PLAYERS + + These functions may/will be reused for future scripts as well. + + -------------------------------------------------------------------- +*/ + +#include "script/KevinSystem/kevin_system/Kevin_ItemConst.txt" +#include "script/KevinSystem/kevin_system/Kevin_ItemLib.txt" +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" +#include "script/KevinSystem/Kevin_PlayerLib_HUD.dnh" +//#include "script/KevinSystem/Universal_Lib.txt" + +float universalAlpha = GetAreaCommonData("Config", "PlayerShotOpacity", 60); + +let POINTER_PIV = LoadAreaCommonDataValuePointer("PIV", "currentvalue", 1000); +let POINTER_CHAIN = LoadAreaCommonDataValuePointer("PIV", "ChainAmount", 1); +let POINTER_CHAINGAUGE = LoadAreaCommonDataValuePointer("PIV", "ChainGauge", 0); +let POINTER_SPECIALAMMO = LoadAreaCommonDataValuePointer("PIV", "SpecialAmmo", 100); +let POINTER_SPECIALCHECK = LoadAreaCommonDataValuePointer("PIV", "IsUsingSpecial", false); +let POINTER_CHAINCHECK = LoadAreaCommonDataValuePointer("PIV", "IsChaining", false); + +//universalAlpha = 255; // Debug + +function CreateTextObject( + float mx, my, size, + string text, font, + int colorTop, colorBottom, + int borderColor, borderWidth, + int renderPriority + ){ + + let obj = ObjText_Create(); + ObjText_SetText(obj, text); + ObjText_SetFontSize(obj, size); + ObjText_SetFontType(obj, font); + ObjText_SetFontColorTop(obj, colorTop); + ObjText_SetFontColorBottom(obj, colorBottom); + ObjText_SetFontBorderType(obj, BORDER_FULL); + ObjText_SetFontBorderColor(obj, borderColor); + ObjText_SetFontBorderWidth(obj, borderWidth); + Obj_SetRenderPriorityI(obj, renderPriority); + ObjRender_SetX(obj, mx); + ObjRender_SetY(obj, my); + return obj; + +} + +function _Create2DImage(imgpath, int[] rectarray){ + + int imgname = ObjPrim_Create(OBJ_SPRITE_2D); + ObjPrim_SetTexture(imgname, imgpath); + ObjSprite2D_SetSourceRect(imgname, rectarray); + ObjSprite2D_SetDestCenter(imgname); + //ObjRender_SetPosition(imgname, positionstart) + + return imgname; +} + +// thanks ttbd owo + +function CreateEffectObject(px, py, img, blendtype, left, top, right, bottom) +{ + let obj = ObjPrim_Create(OBJ_SPRITE_2D); + ObjPrim_SetTexture(obj, img); + ObjSprite2D_SetSourceRect(obj, left, top, right, bottom); + ObjSprite2D_SetDestCenter(obj); + + if(blendtype=="ALPHA"){ObjRender_SetBlendType(obj, BLEND_ALPHA);} + else if(blendtype=="MULTIPLY"){ObjRender_SetBlendType(obj, BLEND_MULTIPLY);} + else if(blendtype=="SUBTRACT"){ObjRender_SetBlendType(obj, BLEND_SUBTRACT);} + else if(blendtype=="SHADOW"){ObjRender_SetBlendType(obj, BLEND_SHADOW);} + else if(blendtype=="RGB"){ObjRender_SetBlendType(obj, BLEND_ADD_RGB);} + else if(blendtype=="ARGB"){ObjRender_SetBlendType(obj, BLEND_ADD_ARGB);} + else if(blendtype=="INVERT"){ObjRender_SetBlendType(obj, BLEND_INV_DESTRGB);} + + ObjRender_SetPosition(obj, px, py, 0); + ObjRender_SetTextureFilter(obj, FILTER_POINT, FILTER_POINT, FILTER_POINT); + + return obj; +} + +/* + +CHAIN SYSTEM: Crystals fill up your chain amount and refill your chain gauge, up to a max of 64x +Gauge starts to go down when you don't collect crystals: it resets the entire chain after 3 seconds + +*/ + +task _HandleChainGauge(){ + + // Gauge maxes at 100. + // If gauge reaches 0, reset the chain + float rateReduceNormal = 100/120; + + float rateReduceCashin = 100/180; // x48-64 + + float rateReduceCashin_MED = 100/90; // x32-48 + float rateReduceCashin_LOW = 100/60; // x16-32 + float rateReduceCashin_PLACEBO = 100/30; // under x16 + + while(true){ + + if(GetCommonDataPtr(POINTER_SPECIALCHECK, false) == false && GetCommonDataPtr(POINTER_CHAIN, 1) >= 64 && !isChain){NotifyEventAll(EV_CHAIN_MAX, 1);} + + else{} + + if(GetCommonDataPtr(POINTER_SPECIALCHECK, false) == true){ + + if(GetCommonDataPtr(POINTER_CHAINGAUGE, 0) <= 1){NotifyEventAll(EV_CHAIN_END, 1);} + + if(GetCommonDataPtr(POINTER_CHAIN, 1) >= 48) + {SetCommonDataPtr(POINTER_CHAINGAUGE, max(0, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)-rateReduceCashin));} + + else if(GetCommonDataPtr(POINTER_CHAIN, 1) >= 32 && GetCommonDataPtr(POINTER_CHAIN, 1) < 48) + {SetCommonDataPtr(POINTER_CHAINGAUGE, max(0, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)-rateReduceCashin_MED));} + + else if(GetCommonDataPtr(POINTER_CHAIN, 1) >= 16 && GetCommonDataPtr(POINTER_CHAIN, 1) < 32) + {SetCommonDataPtr(POINTER_CHAINGAUGE, max(0, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)-rateReduceCashin_LOW));} + + else + {SetCommonDataPtr(POINTER_CHAINGAUGE, max(0, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)-rateReduceCashin_PLACEBO));} + + } + + else{ + SetCommonDataPtr(POINTER_CHAINGAUGE, max(0, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)-rateReduceNormal)); + } + + if( + GetCommonDataPtr(POINTER_CHAINGAUGE, 0) <= 0 + && GetCommonDataPtr(POINTER_CHAIN, 1) > 1 + ) + { + SetCommonDataPtr(POINTER_CHAIN, 1); + SetCommonDataPtr(POINTER_SPECIALCHECK, false); + } + + yield; + + } + +} + +task _ShowChain(){ + + // HUD + + //_ShowChainHUD(); + + // Playfield + + let objPIVNum = ObjText_Create(); + + ObjText_SetFontSize(objPIVNum, 40); + ObjText_SetFontBold(objPIVNum, true); + ObjText_SetFontType(objPIVNum, "GravityRegular5"); + ObjText_SetFontColorTop(objPIVNum, 0xFFFFFF); + ObjText_SetFontColorBottom(objPIVNum, 0xFFFFFF); + ObjText_SetFontBorderType(objPIVNum, BORDER_FULL); + ObjText_SetFontBorderColor(objPIVNum, 0xFF9A4F); + ObjText_SetFontBorderWidth(objPIVNum, 4); + ObjText_SetHorizontalAlignment(objPIVNum, ALIGNMENT_LEFT); + //ObjText_SetFontWeight(objPIVNum, 1000); + Obj_SetRenderPriorityI(objPIVNum, 60); + ObjText_SetSidePitch(objPIVNum, -3); + ObjRender_SetPosition(objPIVNum, STG_WIDTH * 1/2 + 96, STG_HEIGHT * 10/11, 0); + // DEBUG + //Obj_SetVisible(objPIV, false); + + float value = 0; + + //todo: change params + let objI = CreateEffectObject(STG_WIDTH/60, STG_HEIGHT/7, "script/KevinSystem/img/lol.png", "ALPHA", 0, 0, 244, 12); + ObjSprite2D_SetDestRect(objI, 0, 0, 122, 6); + Obj_SetRenderPriorityI(objI, 60); + + while(true){ + value = min(GetCommonDataPtr(POINTER_SPECIALAMMO, 1), 100); + ObjText_SetText(objPIVNum, IntToString(GetCommonDataPtr(POINTER_PIV, 1000))); + + //PIVMultiplierValue = value/1000; + let yass = rtos("00.00", value); + + let mx = 60*5; + ObjSprite2D_SetDestRect(objI, 0, 0, (GetCommonDataPtr(POINTER_SPECIALAMMO, 100)/100)*mx, 32); + + ObjRender_SetPosition(objI, STG_WIDTH/60+160, STG_HEIGHT * 11/12, 1); + + if (GetPlayerY() >= STG_HEIGHT * 7/8){ + ObjRender_SetAlpha(objI, 125); + ObjRender_SetAlpha(objPIVNum, 125); + } + + else{ + ObjRender_SetAlpha(objI, 255); + ObjRender_SetAlpha(objPIVNum, 255); + } + + if (GetCommonDataPtr(POINTER_CHAINCHECK, false) == true) { + ObjRender_SetColor(objI, 0xFFAF1E); + } + else { + if(value >= 100){ + ObjRender_SetColor(objI, 255, 90, 46); + } + else{ + ObjRender_SetColor(objI, 255, 145, 115); + } + } + + /* + if(GetCommonDataPtr(POINTER_SPECIALCHECK, false) == false){ + + ObjText_SetFontBorderWidth(objPIVNum, 3); + + if(value < CHAIN_MAX){ + + ObjText_SetFontColorTop(objPIVNum, 0x9DEFFF); + ObjText_SetFontBorderColor(objPIVNum, 42, 0, 237); + ObjText_SetText(objPIVNum, + "[font size=23 oy=-8]FUN MODE CHARGING[r]" ~ yass ~ "[font size=25 oy=32]x[r]" + ~ "[r][font size=21 oc=(172, 50, 50) oy=32]AMMO: " ~ rtos("00.00", GetCommonDataPtr(POINTER_SPECIALAMMO, 100)) + ); + + } + + else{ + + ObjText_SetFontColorTop(objPIVNum, 0x9DFFBC); + ObjText_SetFontBorderColor(objPIVNum, 0x39C832); + ObjText_SetText(objPIVNum, + "[font size=23 oy=-8]FUN MODE READY![r]" ~ yass ~ "[font size=25 oy=32]x[r]" + ~ "[r][font size=21 oc=(172, 50, 50) oy=32]AMMO: " ~ rtos("00.00", GetCommonDataPtr(POINTER_SPECIALAMMO, 100)) + ); + + } + + } + + else{ + + ObjText_SetFontColorTop(objPIVNum, 0xFFED9D); + ObjText_SetFontBorderColor(objPIVNum, 0xFF9A00); + ObjText_SetFontBorderWidth(objPIVNum, 4); + NotifyEvent(GetPlayerScriptID(), EV_CHAIN_MAX, 0); + ObjText_SetText(objPIVNum, + "[font size=23 oc=(241, 180, 0) oy=-8]CASH-IN[r]" ~ yass ~ "[font size=25 oy=32]x[r]" + ~ "[r][font size=21 oc=(172, 50, 50) oy=32]AMMO: " ~ rtos("00.00", GetCommonDataPtr(POINTER_SPECIALAMMO, 100)) + ); + + } + */ + + yield; + } + +} + +// Self-explanatory + +task _DeleteEffect(obj, scale){ + ObjRender_SetBlendType(obj, BLEND_ADD_ARGB); + Obj_SetRenderPriorityI(obj, 49); + ascent(i in 0..30){ + ObjRender_SetAlpha(obj, Interpolate_Decelerate(100*(universalAlpha/100), 0, i/30)); + ObjRender_SetScaleXYZ(obj, Interpolate_Decelerate(scale, scale*1.5, i/20)); + ObjMove_SetSpeed(obj, 12); + yield; + } + Obj_Delete(obj); +} + +// Renders player movement. Assumes that all sprites are ORGANIZED HORIZONTALLY IN THE SHEET. +// flipscale can only be 1 or -1. + +task _RenderPlayerMovement(int obj, int frame, int offsetleft, int offsettop, int width, int height, float flipscale, int frameno, int speed){ + + ObjSprite2D_SetSourceRect(obj, offsetleft+width*floor(frame/speed), offsettop, width+width*floor(frame/speed), offsettop+height); + ObjRender_SetScaleX(objPlayer, flipscale); + +} + +// Bullet rescaling... for player shots. +task _BulletRescalePlayer(int target, float scale, bool hitboxscale, float hitboxlevel){ + ObjRender_SetScaleXYZ(target, scale, scale, 1); + if (hitboxscale){ + ObjShot_SetIntersectionScaleXY(target, scale*hitboxlevel, scale*hitboxlevel); + } +} + +// Handles death/respawn sigil. Assumes sigils are 512x512 in size. +// If death is true (the player dies), the circle expands outwards. Otherwise (the player bombs/respawns), it shrinks inwards. + +task _SigilCall(bool death, texture, int rectleft, int recttop, int rectright, int rectbottom, int objPlayer, int time){ + + let DeathCircle = ObjPrim_Create(OBJ_SPRITE_2D); + + ObjPrim_SetTexture(DeathCircle,teamimg); + ObjSprite2D_SetSourceRect(DeathCircle, rectleft, recttop, rectright, rectbottom); + ObjSprite2D_SetDestCenter(DeathCircle); + ObjRender_SetBlendType(DeathCircle,BLEND_ALPHA); + ObjRender_SetAlpha(DeathCircle,255); + + ObjRender_SetPosition(DeathCircle,GetPlayerX(),GetPlayerY(),1); + Obj_SetRenderPriorityI(DeathCircle,Obj_GetRenderPriorityI(objPlayer)-10); + + alternative(death) + case(true){ + ascent(i in 0..time){ + float scaliealpha = Interpolate_Decelerate(255, 0, i/time); + float scaliesize = Interpolate_Decelerate(0.1, 3, i/time); + ObjRender_SetAlpha(DeathCircle, scaliealpha); + ObjRender_SetPosition(DeathCircle,GetPlayerX(),GetPlayerY(),1); + ObjRender_SetScaleXYZ(DeathCircle, scaliesize, scaliesize, 1); + yield; + } + } + case(false){ + ascent(i in 0..time){ + float scaliealpha = Interpolate_Accelerate(255, 0, i/time); + float scaliesize = Interpolate_Accelerate(3, 0.1, i/time); + ObjRender_SetAlpha(DeathCircle, scaliealpha); + ObjRender_SetPosition(DeathCircle,GetPlayerX(),GetPlayerY(),1); + ObjRender_SetScaleXYZ(DeathCircle, scaliesize, scaliesize, 1); + yield; + } + } + + + while(ObjRender_GetAlpha(DeathCircle) > 0){yield;} + Obj_Delete(DeathCircle); + +} + +// Handles the hitbox and its aura. What the fuck. + +task _HitboxRender( + bool playerdeathbool, int objPlayer, texture_hbox, texture_aura, + int rectleft_hbox, int recttop_hbox, int rectright_hbox, int rectbottom_hbox, + int rectleft_aura, int recttop_aura, int rectright_aura, int rectbottom_aura, + float scale_hbox, float scale_aura){ + + // Handle hitbox + bool visible = false; + int hitbox = ObjPrim_Create(OBJ_SPRITE_2D); + + ObjPrim_SetTexture(hitbox, texture_hbox); + ObjSprite2D_SetSourceRect(hitbox, rectleft_hbox, recttop_hbox, rectright_hbox, rectbottom_hbox); + ObjSprite2D_SetDestCenter(hitbox); + ObjRender_SetScaleXYZ(hitbox, scale_hbox, scale_hbox, 1); + ObjRender_SetBlendType(hitbox, BLEND_ALPHA); + Obj_SetRenderPriorityI(hitbox, 79); + + Obj_SetVisible(hitbox, false); + + // Handle hitbox's aura + + int aura = ObjPrim_Create(OBJ_SPRITE_2D); + + ObjPrim_SetTexture(aura, texture_aura); + ObjSprite2D_SetSourceRect(aura, rectleft_aura, recttop_aura, rectright_aura, rectbottom_aura); + ObjSprite2D_SetDestCenter(aura); + ObjRender_SetScaleXYZ(aura, scale_aura, scale_aura, 1); + ObjRender_SetAlpha(aura, 70); + //ObjRender_SetBlendType(aura, BLEND_ADD_ARGB); + Obj_SetRenderPriorityI(aura, Obj_GetRenderPriorityI(objPlayer)+3); + + Obj_SetVisible(aura, false); + + loop{ + if (visible && (!Obj_IsVisible(objPlayer) || GetVirtualKeyState(VK_SLOWMOVE) != KEY_HOLD)){ + visible = false; + Obj_SetVisible(hitbox, false); + Obj_SetVisible(aura, false); + } + else if (!visible && (Obj_IsVisible(objPlayer) && (GetVirtualKeyState(VK_SLOWMOVE) == KEY_HOLD || GetVirtualKeyState(VK_SLOWMOVE) == KEY_PUSH))){ + visible = true; + Obj_SetVisible(aura, true); + Obj_SetVisible(hitbox, true); + async{ + while(Obj_IsVisible(aura)){ + float[] curang = [ObjRender_GetAngleZ(hitbox), ObjRender_GetAngleZ(aura)]; + ObjRender_SetAngleZ(hitbox, curang[0]+1.5); + ObjRender_SetAngleZ(aura, curang[1]+1.5); + yield; + } + } + async{ + ascent(i in 0..20){ + float scalie = Interpolate_Decelerate(scale_aura*1.5, scale_aura, i/20); + ObjRender_SetScaleXYZ(aura, scalie, scalie, 1); + yield; + } + } + + async{ + ascent(i in 0..20){ + float scalie = Interpolate_Decelerate(0, 80, i/20); + ObjRender_SetAlpha(aura, scalie); + yield; + } + } + } + ObjRender_SetPosition(hitbox, ObjMove_GetX(objPlayer), ObjMove_GetY(objPlayer), 1); + ObjRender_SetPosition(aura, ObjMove_GetX(objPlayer), ObjMove_GetY(objPlayer), 1); + yield; + } + +} + +/* +Simple function that handles player options. These options simply follow the player at an offset - they do not have any trajectories of their own like spinning around the player, etc. +If the options have animations, set triggeranimation to true and adjust the number of frames + speed using delay and frameno. +If the options rotate (in place), set triggerspin to true and adjust spinning speed using spinspeed. +If the options only appear unfocused or focused, set either onlyFocus or onlyUnfocus to true. Setting both to true or false makes the options always visible. +*/ + +function PlayerOption( + float offsetx, float offsety, + texture, + int left, int top, int right, int bottom, float scale, + int width, int animdelay, int frameno, bool triggeranimation, + bool triggerspin, float spinspeed, + bool onlyFocus, bool onlyUnfocus + ){ + + let option = ObjPrim_Create(OBJ_SPRITE_2D); + bool visible; + int animate = 0; + float optx; + float opty; + + ObjPrim_SetTexture(option, texture); + ObjSprite2D_SetSourceRect(option, left, top, right-1, bottom-1); // Allows the options to spin smoothly should the user choose to do so. + ObjSprite2D_SetDestCenter(option); + ObjRender_SetScaleXYZ(option, scale); + ObjRender_SetBlendType(option, BLEND_ALPHA); + ObjRender_SetAlpha(option, 255); + Obj_SetRenderPriorityI(option, 41); + ObjRender_SetPosition(option, offsetx, offsety, 1); + + // Animation + async{ + while(triggeranimation){ + ObjSprite2D_SetSourceRect(option, left+width*floor(animate/animdelay), top, right+width*floor(animate/animdelay)-1, bottom-1); + animate++; + if (animate >= animdelay*frameno){animate = 0;} + yield; + } + } + + // Rotation + async{ + float i = 0; + while(triggerspin){ + //ObjRender_SetPosition(option, GetPlayerX()+offsetx, GetPlayerY()+offsety, 1); + ObjRender_SetAngleZ(option, i); + i += spinspeed; + yield; + } + } + + // Follow + async{ + while(true){ + ObjRender_SetPosition(option, GetPlayerX()+offsetx, GetPlayerY()+offsety, 1); + yield; + } + } + + // Visibility + async{ + // Always visible + if((onlyFocus && onlyUnfocus) || (!onlyFocus && !onlyUnfocus)) { + loop + { + if(GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;} + else {ObjRender_SetAlpha(option, min(225, ObjRender_GetAlpha(option)+15)); visible = true;} + yield; + } + } + // Visible when focused only + else if(onlyFocus && !onlyUnfocus){ + loop + { + if((GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT) || GetVirtualKeyState(VK_SLOWMOVE) == KEY_FREE){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;} + else {ObjRender_SetAlpha(option, min(225, ObjRender_GetAlpha(option)+15)); visible = true;} + yield; + } + } + // Visible when unfocused only + else if(!onlyFocus && onlyUnfocus){ + loop + { + if((GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT) || GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;} + else {ObjRender_SetAlpha(option, min(225, ObjRender_GetAlpha(option)+15)); visible = true;} + yield; + } + } + } + + function _FadeIn(){ + ascent(i in 0..15){ + ObjRender_SetAlpha(option, Interpolate_Decelerate(0, 225, i/15)); + yield; + } + } + + function _FadeOut(){ + ascent(i in 0..15){ + ObjRender_SetAlpha(option, Interpolate_Decelerate(225, 0, i/15)); + yield; + } + } + + return option; +} + +/* +A form of PlayerOption that handles basic movement towards different positionings based on whether the player is focusing or unfocusing. +If the options have animations, set triggeranimation to true and adjust the number of frames + speed using delay and frameno. +If the options rotate (in place), set triggerspin to true and adjust spinning speed using spinspeed. +If the options only appear unfocused or focused, set either onlyFocus or onlyUnfocus to true. Setting both to true or false makes the options always visible. +*/ + +function PlayerOption_LinearMove( + float offsetX_uf, offsetY_uf, offsetX_f, offsetY_f, + bool angchange, float ang_uf, ang_f, + texture, + int graphic, float texScale, int priorityRender, + int texWidth, int animDelay, int animFrameNo, bool animMode, + bool spinMode, float spinSpeed, + bool onlyFocus, bool onlyUnfocus + ){ + + int option = CreatePlayerShotA1(0, 0, 0, 0, 0, 9999999, graphic); + bool visible; + int animate = 0; + float optx; + float opty; + + float playerX = 0, playerY = 0; + + /* + ObjPrim_SetTexture(option, texture); + ObjSprite2D_SetSourceRect(option, texRect[0], texRect[1], texRect[2]-1, texRect[3]-1); // Allows the options to spin smoothly should the user choose to do so. + ObjSprite2D_SetDestCenter(option); + */ + + ObjShot_SetAutoDelete(option, false); + ObjRender_SetScaleXYZ(option, texScale); + ObjRender_SetBlendType(option, BLEND_ALPHA); + //ObjRender_SetAlpha(option, 255); + Obj_SetRenderPriorityI(option, priorityRender); + ObjRender_SetPosition(option, playerX+offsetX_uf, playerY+offsetY_uf, 1); + + ///// MISC ///// + async{ + while(true){ + playerX = ObjRender_GetX(GetPlayerObjectID()); + playerY = ObjRender_GetY(GetPlayerObjectID()); + yield; + } + } + + ///// ANIMATION ///// + + /* + async{ + while(animMode){ + ObjSprite2D_SetSourceRect(option, texRect[0]+texWidth*floor(animate/animDelay), texRect[1], texRect[2]+texWidth*floor(animate/animDelay)-1, texRect[3]-1); + animate++; + if (animate >= animDelay*animFrameNo){animate = 0;} + yield; + } + }*/ + + ///// ROTATION ///// + async{ + float i = 0; + while(spinMode){ + //ObjRender_SetPosition(option, GetPlayerX()+offsetx, GetPlayerY()+offsety, 1); + ObjRender_SetAngleZ(option, i); + i += spinSpeed; + yield; + } + } + + ///// VISIBILITY ///// + async{ + // Always visible + if((onlyFocus && onlyUnfocus) || (!onlyFocus && !onlyUnfocus)) { + loop + { + if(GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;} + else {ObjRender_SetAlpha(option, min(255, ObjRender_GetAlpha(option)+15)); visible = true;} + yield; + } + } + // Visible when focused only + else if(onlyFocus && !onlyUnfocus){ + loop + { + if((GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT) || GetVirtualKeyState(VK_SLOWMOVE) == KEY_FREE){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;} + else {ObjRender_SetAlpha(option, min(255, ObjRender_GetAlpha(option)+15)); visible = true;} + yield; + } + } + // Visible when unfocused only + else if(!onlyFocus && onlyUnfocus){ + loop + { + if((GetPlayerState != STATE_NORMAL && GetPlayerState != STATE_HIT) || GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ObjRender_SetAlpha(option, max(0, ObjRender_GetAlpha(option)-15)); visible = false;} + else {ObjRender_SetAlpha(option, min(255, ObjRender_GetAlpha(option)+15)); visible = true;} + yield; + } + } + } + + ///// MOVEMENT ///// + async{ + + loop{ + + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + + async{ + + ascent(i in 0..15){ + if(angchange){ObjRender_SetAngleZ(option, Interpolate_Decelerate(ObjRender_GetAngleZ(option), ang_f, i/15));} + ObjRender_SetX(option, Interpolate_Decelerate(ObjRender_GetX(option), playerX+offsetX_f, i/15)); + ObjRender_SetY(option, Interpolate_Decelerate(ObjRender_GetY(option), playerY+offsetY_f, i/15)); + yield; + } + + } + + } + + else{ + + async{ + + ascent(i in 0..15){ + if(angchange){ObjRender_SetAngleZ(option, Interpolate_Decelerate(ObjRender_GetAngleZ(option), ang_uf, i/15));} + ObjRender_SetX(option, Interpolate_Decelerate(ObjRender_GetX(option), playerX+offsetX_uf, i/15)); + ObjRender_SetY(option, Interpolate_Decelerate(ObjRender_GetY(option), playerY+offsetY_uf, i/15)); + yield; + } + + } + + } + + yield; + } + + } + + function _FadeIn(){ + ascent(i in 0..15){ + ObjRender_SetAlpha(option, Interpolate_Decelerate(0, 225, i/15)); + yield; + } + } + + function _FadeOut(){ + ascent(i in 0..15){ + ObjRender_SetAlpha(option, Interpolate_Decelerate(225, 0, i/15)); + yield; + } + } + + return option; +} + +/* +------------------------------------------------------ + + POINTBLANK-PIV MECHANIC FUNCTIONS + Will be optimized somewhere down the line. + +------------------------------------------------------ +*/ + +// Selects an enemy in the @MainLoop-updated _enemyArray, executes _PetalDrop, and adds it to _existArray so the task isn't called again for the same enemy. maxX and maxY are the bounds of the playing field. + +task _Mechanic(bool playerdeathbool, int[] _enemyArray, int [] _existArray, float maxX, float maxY, int objPlayer, int bossScene, int maxrate, int addrate, float adddist){ + while(!playerdeathbool){ + _enemyArray = GetIntersectionRegistedEnemyID(); + bossScene = GetEnemyBossSceneObjectID(); + for each (int enemy in ref _enemyArray){ + float enemyX = ObjMove_GetX(enemy); + float enemyY = ObjMove_GetY(enemy); + if (0 < enemyX && enemyX < maxX && 0 < enemyY && enemyY < maxY && !contains(_existArray, enemy)){ + _PetalDrop(enemy, playerdeathbool, objPlayer, bossScene, maxrate, addrate, adddist); + _existArray = _existArray ~ [enemy]; + } + else{continue;} + } + yield; + } +} + +// Checks the boss scene type (nonspell/spell/last spell/invalid), the ID of the player object, and the target enemy. Drops petals with a type and drop rate that depends on the boss scene type and how close the player is to the target enemy. + +task _PetalDrop(int target, bool playerdeathbool, int objPlayer, int bossScene, int maxrate, int addrate, float adddist){ + + while(!Obj_IsDeleted(target) && !playerdeathbool){ + float dist = hypot(ObjMove_GetX(target)-ObjMove_GetX(objPlayer), ObjMove_GetY(target)-ObjMove_GetY(objPlayer)); + let atktype = GetEnemyBossSceneObjectID(); + if(dist <= (GetStgFrameHeight()-100) && atktype != ID_INVALID && ObjEnemy_GetInfo(target, INFO_SHOT_HIT_COUNT) >= 1 && ObjEnemy_GetInfo(target, INFO_DAMAGE_PREVIOUS_FRAME) > 0){ + + wait(maxrate + addrate*floor(dist/adddist)); + + } + else{yield;} + } + +} + +task _DeathbombWarning(imgpath, int[] imgrectarray, int deathbombframes, float basescale){ + + int circle = _Create2DImage(imgpath, imgrectarray); + Obj_SetRenderPriorityI(circle, 75); + ObjRender_SetAlpha(circle, 255); + ObjRender_SetPosition(circle, ObjRender_GetX(GetPlayerObjectID()), ObjRender_GetY(GetPlayerObjectID()), 1); + ObjRender_SetBlendType(circle, BLEND_INV_DESTRGB); + + ascent(i in 0..deathbombframes-1){ + ObjRender_SetScaleXYZ(circle, Interpolate_Accelerate(basescale, 0, i/(deathbombframes-1))); + yield; + } + + Obj_Delete(circle); + return; + +} + +task _BombShake(shaketime, intensity){ + + float baseintensity = intensity; + float shakeno = shaketime; + + ascent(i in 0..shakeno){ + Set2DCameraFocusX(GetStgFrameWidth/2 + rand(-intensity, intensity)); + Set2DCameraFocusY(GetStgFrameHeight/2 + rand(-intensity, intensity)); + intensity = Interpolate_Decelerate(0, baseintensity, 1-i/shakeno); + shaketime--; + yield; + } + + while(shaketime > 0){yield;} + + Set2DCameraFocusX(GetStgFrameWidth/2); + Set2DCameraFocusY(GetStgFrameHeight/2); + yield; +} + +task _Countdown(){ + + //_FunIndicator; + + //int timer = time; + int counter = CreateTextObject( + playerX, playerY, 45, + "", "GravityRegular5", + 0xFFFFFF, 0xFFFFFF, + 0x1AEC8C, 8, + 51 + ); + + int counter2 = CreateTextObject( + 1720, 870, 40, + "", "Unispace", + 0xFFFFFF, 0xFFFFFF, + 0x1AEC8C, 2, + 19 + ); + + ObjText_SetHorizontalAlignment(counter, ALIGNMENT_CENTER); + + while(true){ + + if(GetPlayerInvincibilityFrame() <= 0){Obj_SetVisible(counter, false);} + else{Obj_SetVisible(counter, true);} + ObjRender_SetPosition(counter, playerX, playerY - 96, 1); + ObjText_SetText(counter, IntToString(GetPlayerInvincibilityFrame())); + ObjText_SetText(counter2, IntToString(GetPlayerInvincibilityFrame())); + yield; + + } + + //Obj_Delete(counter); + +} + +task _FunIndicator(){ + + int counter = CreateTextObject( + 1720, 910, 41, + "FUN IS PREPARED", "Origami Mommy", + 0xFFD9B8, 0xFFFFFF, + 0xD96600, 4, + 39 + ); + + ObjText_SetHorizontalAlignment(counter, ALIGNMENT_CENTER); + + while(true){ + + if(GetCommonDataPtr(POINTER_CHAIN, 1) >= 64 && GetCommonDataPtr(POINTER_SPECIALCHECK, false) == false) + + {Obj_SetVisible(counter, true);} + + else{Obj_SetVisible(counter, false);} + + ObjRender_SetPosition(counter, playerX, playerY + 128, 1); + + yield; + + } + + //Obj_Delete(counter); + +} \ No newline at end of file diff --git a/script/KevinSystem/Kevin_PlayerLib_HUD.dnh b/script/KevinSystem/Kevin_PlayerLib_HUD.dnh new file mode 100644 index 0000000..3f5030e --- /dev/null +++ b/script/KevinSystem/Kevin_PlayerLib_HUD.dnh @@ -0,0 +1,133 @@ +task _ShowChainHUD(){ + + // Playfield + + // Multiplier + + async{ + + let objPIVNum = ObjText_Create(); + + // AAAAAAA WHYYYYYYY + + ObjText_SetFontSize(objPIVNum, 60); + ObjText_SetFontBold(objPIVNum, true); + ObjText_SetFontType(objPIVNum, "Origami Mommy"); + ObjText_SetFontColorTop(objPIVNum, 0xFFFFFF); + ObjText_SetFontColorBottom(objPIVNum, 0xFFFFFF); + ObjText_SetFontBorderType(objPIVNum, BORDER_FULL); + ObjText_SetFontBorderColor(objPIVNum, 95, 209, 255); + ObjText_SetFontBorderWidth(objPIVNum, 4); + ObjText_SetHorizontalAlignment(objPIVNum, ALIGNMENT_LEFT); + Obj_SetRenderPriorityI(objPIVNum, 19); + ObjText_SetSidePitch(objPIVNum, -3); + ObjRender_SetPosition(objPIVNum, 32, 128, 0); + // DEBUG + //Obj_SetVisible(objPIV, false); + + float value = 0; + + while(true){ + value = min(GetCommonDataPtr(POINTER_CHAIN, 1), CHAIN_MAX); + //PIVMultiplierValue = value/1000; + let yass = rtos("00.00", value); + + if(GetCommonDataPtr(POINTER_SPECIALCHECK, false) == false){ + + ObjText_SetFontBorderWidth(objPIVNum, 3); + + if(value < CHAIN_MAX){ + + ObjText_SetFontBorderColor(objPIVNum, 42, 0, 237); + ObjText_SetText(objPIVNum, + yass ~ "[font size=25 oy=32]x" + ); + + } + + else{ + + ObjText_SetFontBorderColor(objPIVNum, 0, 240, 117); + ObjText_SetText(objPIVNum, + yass ~ "[font size=25 oy=32]x" + ); + + } + + } + + else{ + + ObjText_SetFontBorderColor(objPIVNum, 0xFF9A00); + ObjText_SetText(objPIVNum, + yass ~ "[font size=25 oy=32]x" + ); + + } + + yield; + } + + } + + // Chain Timer + + async{ + + let timerText = CreateTextObject( + 275, 210, 32, + "", "Unispace", + 0xB5FFEE, 0xFFFFFF, + 0x397D88, 2, + 19 + ); + + while(true){ + ObjText_SetText(timerText, IntToString(GetCommonDataPtr(POINTER_CHAINGAUGE, 100))); + yield; + } + + } + + // Chain Status + + async{ + + let timerText = CreateTextObject( + 275, 255, 32, + "", "Unispace", + 0xFFE0A2, 0xFFFFFF, + 0xCB6D00, 2, + 19 + ); + + while(true){ + ObjText_SetText(timerText, GetCommonDataPtr(POINTER_SPECIALCHECK, false) ? "ACTIVE" : "INACTIVE"); + ObjText_SetFontBorderColor(timerText, GetCommonDataPtr(POINTER_SPECIALCHECK, false) ? 0xCB6D00 : 0x67A41E); + ObjText_SetFontColorTop(timerText, GetCommonDataPtr(POINTER_SPECIALCHECK, false) ? 0xFFE0A2 : 0xD8FFA8); + yield; + } + + } + + // Ammo Status + + async{ + + let ammoText = CreateTextObject( + 1585, 445, 48, + "", "Unispace", + 0xFFB8A0, 0xFFFFFF, + 0xC53000, 2, + 19 + ); + + ObjText_SetFontBold(ammoText, true); + while(true){ + ObjText_SetText(ammoText, rtos("000.00", GetCommonDataPtr(POINTER_SPECIALAMMO, 100)) ~ "[font sz=24 oy=20]/100.00"); + yield; + } + + } + +} \ No newline at end of file diff --git a/script/KevinSystem/Kevin_System.txt b/script/KevinSystem/Kevin_System.txt new file mode 100644 index 0000000..94d48cb --- /dev/null +++ b/script/KevinSystem/Kevin_System.txt @@ -0,0 +1,926 @@ + +// SYSTEM FOR STATION GAME + +let dirCurrent = GetCurrentScriptDirectory(); + +// Change accordingly! + +int offsetX = 1551; +int baseY = 155; +int spaceY = 135; +float scale = 1.15*1.6; + +int sel = 0; + +// Item, life, spell graphics + +let graphicimg = dirCurrent ~ "./img/yo.png"; +let lifebarimg = dirCurrent ~ "./img/lifebar.png"; +LoadTextureEx(graphicimg, true, true); + +let pointerPIV; + +//#include "./../script/soundtask.txt" + +#include "script/KevinSystem/Init.dnh" +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" +#include "script/KevinSystem/GeneralSoundLib.txt" +#include "script/default_system/Default_Effect.txt" +#include "script/KevinSystem/kevin_system/Kevin_EffectLib.dnh" + +@Initialize +{ + + if(!IsCommonDataAreaExists("PIV")){ + CreateCommonDataArea("PIV"); + SetAreaCommonData("PIV", "currentvalue", 10000); + } + else{} + + pointerPIV = LoadAreaCommonDataValuePointer("PIV", "currentvalue", 10000); + + _SoundTask(); + + SetAreaCommonData("ScriptID", "SystemID", GetOwnScriptID()); + + //SetCommonDataPtr("SystemIDPtr", GetOwnScriptID()); + + SetStgFrame(0, 0, 1280, 720, 20, 80); + + sel = prand_int(0, 99); + + // Pixel art + + SetShotTextureFilter(FILTER_NONE, FILTER_NONE); + SetItemTextureFilter(FILTER_NONE, FILTER_NONE); + + SetPauseScriptPath(GetCurrentScriptDirectory() ~ "kevin_system/Kevin_Pause.txt"); + SetEndSceneScriptPath(GetCurrentScriptDirectory() ~ "kevin_system/Kevin_EndScene.txt"); + SetReplaySaveSceneScriptPath(GetCurrentScriptDirectory() ~ "kevin_system/Kevin_ReplaySave.txt"); + + InitEffect(); + InitFrame(); + + //TInstallFont(); Moved to package. + + TScore(); + LifeDisplay(); + + //TGraze(); + //SetPlayerLife(9); + //SpellDisplay(); + THighScore(); + //TValueDisplay(); + + StartItemScript(dirCurrent ~ "./kevin_system/KevinSystem_Item.txt"); + + TExtendSystem(); + //TBossLife(); + TBossTimer(); + + TCurrentFps(); + TReplayFps(); + //_SoundTask; +} + +@MainLoop +{ + yield; +} + +@Event +{ + alternative(GetEventType()) + + case(EV_START_BOSS_SPELL) + { + let path = dirCurrent ~ "Default_System_MagicCircle.txt"; + let id = LoadScript(path); + StartScript(id); + } + + case(EV_GAIN_SPELL) + { + let objScene = GetEnemyBossSceneObjectID(); + let spellbonus = ObjEnemyBossScene_GetInfo(objScene, INFO_SPELL_SCORE); + TScoreAward(spellbonus); + } + + // Arguments: [enemy x, y], particle list to use + + case(EV_EXPLODE) + { + float[] pos = GetEventArgument(0); + //int listTarget = GetEventArgument(1); + + if(GetCommonDataPtr(EFFECTCUT_PTR, 0) >= 2){ObjSound_Play(sfxBoom);} + //_EffectListPreRender(PetalEffect, imgEffect, [0, 0, 256, 256]); + else{_ExplosionEffect(pos[0], pos[1], PetalEffect);} + + } + +} + +function CreateTextObject( + float mx, my, size, + string text, font, + int colorTop, colorBottom, + int borderColor, borderWidth, + int renderPriority + ){ + + let obj = ObjText_Create(); + ObjText_SetText(obj, text); + ObjText_SetFontSize(obj, size); + ObjText_SetFontType(obj, font); + ObjText_SetFontColorTop(obj, colorTop); + ObjText_SetFontColorBottom(obj, colorBottom); + ObjText_SetFontBorderType(obj, BORDER_FULL); + ObjText_SetFontBorderColor(obj, borderColor); + ObjText_SetFontBorderWidth(obj, borderWidth); + Obj_SetRenderPriorityI(obj, renderPriority); + ObjRender_SetX(obj, mx); + ObjRender_SetY(obj, my); + return obj; + +} + +// Grants extends based on score + +task TExtendSystem(){ + + // NEXT: Text (y around 650?) (x around 2250?) + + /*let NextText = + + CreateTextObject( + 1625, 465, 30, + "NEXT:", "Connecting Chain Handserif", + 0xA70053, 0xA70053, + 0xFFFFFF, 2, + 1 + );*/ + + //ObjText_SetFontBold(NextText, true); + // Indicates the score threshold needed for the next extend + + let ExtendThresholdText = + + CreateTextObject( + 1450, 160, 28, + "", "Unispace", + 0xFF98A9, 0xFFFFFF, + 0x000000, 4, + 2 + ); + + ObjText_SetFontBold(ExtendThresholdText, true); + ObjText_SetHorizontalAlignment(ExtendThresholdText, ALIGNMENT_LEFT); + + int len = 0; + int count = 0; + // Millions + let req = [ + + ]; + + alternative(GetCommonData("Difficulty", "Standard")) + + case("Novice"){ + req = [250, 500, 1000, 1800]; + len = 3; + } + + case("Standard"){ + req = [400, 800, 1500, 2500]; + len = 3; + } + + others{ + req = [1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 11000, 12000, 13000, 14000, 15000, 16000, 17000, 18000, 19000, 20000]; + len = 19; + } + + let next = 0; + + // NARUMISTG + + req = [ + 10, 20, 40, 80, 120 + ]; + + loop{ + count = (trunc(GetScore())/10)*10; + if(next <= length(req)-1){ + if(count >= req[next]*1000000){ + next++; + SetPlayerLife(GetPlayerLife+1); + ExtendSFX; + ExtendEffect; + } + } + + if(next <= len){ObjText_SetText(ExtendThresholdText, "[font tc=(255, 43, 78) bc=(255, 128, 149)]NEXT: [font clr]" ~ DigitToCommaArray(req[next]*1000000));} + + else{ObjText_SetText(ExtendThresholdText, "MAXIMUM");} + yield; + } +} + +task ExtendEffect(){ + + int time = 30; + int timeDisappear = 30; + + float x = GetPlayerX(); + float y = GetPlayerY()-90; + + int extendText = CreateTextObject( + x, y, 75, + "Life[r]Extend!", "Exotc350 DmBd BT", + 0xFF61AE, 0xFFFFFF, + 0x5E0064, 6, + 42 + ); + + ObjText_SetLinePitch(extendText, -2); + ObjText_SetFontBold(extendText, true); + ObjText_SetHorizontalAlignment(extendText, ALIGNMENT_CENTER); + + ascent(i in 0..time){ + ObjRender_SetY(extendText, Interpolate_Decelerate(y, y-120, i/time)); + yield; + } + + wait(15); + + ascent(i in 0..timeDisappear){ + ObjRender_SetAlpha(extendText, Interpolate_Decelerate(255, 0, i/timeDisappear)); + yield; + } + Obj_Delete(extendText); + +} + +//---------------------------------------------------- +//枠外の背景表示 +//---------------------------------------------------- +task InitFrame() +{ + let path1 = GetCurrentScriptDirectory() ~ "img/HUD1.png"; + let path2 = GetCurrentScriptDirectory() ~ "img/HUD2.png"; + + let obj1 = ObjPrim_Create(OBJ_SPRITE_2D); + let obj2 = ObjPrim_Create(OBJ_SPRITE_2D); + + LoadTextureEx(path1, true, true); + LoadTextureEx(path2, true, true); + + ObjPrim_SetTexture(obj1, path1); + ObjPrim_SetTexture(obj2, path2); + + int[] arr = [obj1, obj2]; + + for each(int obj in ref arr){ + + ObjRender_SetTextureFilterMag(obj, FILTER_NONE); + ObjRender_SetTextureFilterMin(obj, FILTER_NONE); + ObjRender_SetTextureFilterMip(obj, FILTER_NONE); + Obj_SetRenderPriority(obj, 79); + ObjSprite2D_SetSourceRect(obj, 0, 0, GetScreenWidth(), GetScreenHeight()); + ObjSprite2D_SetDestRect(obj, 0, 0, GetScreenWidth(), GetScreenHeight()); + + } + + // If player moves to vertical bounds, lower opacity + + while(true){ + + if(GetPlayerY() > GetStgFrameHeight() * 7/8){ + ObjRender_SetAlpha(obj2, 125); + } + else{ObjRender_SetAlpha(obj2, 255);} + + if(GetPlayerY() < GetStgFrameHeight() * 1/8){ + ObjRender_SetAlpha(obj1, 125); + } + else{ObjRender_SetAlpha(obj1, 255);} + + yield; + + } +} + +//---------------------------------------------------- +//スコア表示 +//---------------------------------------------------- + +task THighScore(){ + + let DATA_PLAYER = GetPlayerReplayName(); + let DATA_DIFFICULTY = GetCommonData("Difficulty", "Standard"); + + let objScoreNo = ObjText_Create(); + ObjText_SetFontSize(objScoreNo, 32); + ObjText_SetFontBold(objScoreNo, true); + ObjText_SetFontType(objScoreNo, "GravityBold8"); + ObjText_SetFontColorTop(objScoreNo, 0xFFFFFF); + ObjText_SetFontColorBottom(objScoreNo, 0xFFB061); + ObjText_SetFontBorderType(objScoreNo, BORDER_FULL); + ObjText_SetFontBorderColor(objScoreNo, 0xAB3D00); + ObjText_SetFontBorderWidth(objScoreNo, 4); + //ObjText_SetFontWeight(objScoreNo, 1000); + Obj_SetRenderPriorityI(objScoreNo, 79); + ObjText_SetSidePitch(objScoreNo, -2); + ObjRender_SetPosition(objScoreNo, 192, 12, 0); + + while(true){ + let score = GetAreaCommonData("Data_" ~ DATA_PLAYER, "HighScore_" ~ DATA_DIFFICULTY, 0); + score = min(score,999999999990); + let yass = DigitToCommaArray(score); + ObjText_SetText(objScoreNo, yass); + yield; + } +} + +task TScore(){ + // New score system using rtos + + // For score with zeroes at the end: Truncate score/10, and then multiply it by 10 + + let objScoreNo = ObjText_Create(); + ObjText_SetFontSize(objScoreNo, 32); + ObjText_SetFontBold(objScoreNo, true); + ObjText_SetFontType(objScoreNo, "GravityBold8"); + ObjText_SetFontColorTop(objScoreNo, 0xFFFFFF); + ObjText_SetFontColorBottom(objScoreNo, 0x8944CE); + ObjText_SetFontBorderType(objScoreNo, BORDER_FULL); + ObjText_SetFontBorderColor(objScoreNo, 0x391339); + ObjText_SetFontBorderWidth(objScoreNo, 4); + //ObjText_SetFontWeight(objScoreNo, 1000); + Obj_SetRenderPriorityI(objScoreNo, 79); + ObjText_SetSidePitch(objScoreNo, -2); + ObjRender_SetPosition(objScoreNo, 192, 56, 0); + while(true){ + + if(GetPlayerY() < GetStgFrameHeight() * 1/8){ + ObjRender_SetAlpha(objScoreNo, 125); + } + else{ObjRender_SetAlpha(objScoreNo, 255);} + + let score = trunc(GetScore()/10) * 10; + score = min(score,999999999990); + let yass = DigitToCommaArray(score); + ObjText_SetText(objScoreNo, yass); + + yield; + } +} + +function DigitToCommaArray(num){ //Natashinitai + + let srcStr = IntToString(num); + let res = []; + let nChar = 0; + for(let i = length(srcStr) - 1; i >= 0; i--){ + res = [srcStr[i]] ~ res; + nChar++; + if(nChar % 3 == 0 && i > 0) res = "," ~ res; + } + return res; + +} + +//---------------------------------------------------- +//Graze表示 +//---------------------------------------------------- +task TGraze() +{ + let grazenum = ObjText_Create(); + ObjText_SetFontSize(grazenum, 58); + ObjText_SetFontBold(grazenum, true); + ObjText_SetFontType(grazenum, "Anke Calligraph"); + ObjText_SetFontColorTop(grazenum, 0x8898A3); + ObjText_SetFontColorBottom(grazenum, 0xD2E0FF); + ObjText_SetFontBorderType(grazenum, BORDER_FULL); + ObjText_SetFontBorderColor(grazenum, 0xFFFFFF); + ObjText_SetFontBorderWidth(grazenum, 3); + Obj_SetRenderPriorityI(grazenum, 1); + ObjRender_SetX(grazenum, offsetX-10); + ObjRender_SetY(grazenum, baseY*0.8+spaceY*5); + + while(true){ + let graze = GetGraze(); + + ObjText_SetText(grazenum, rtos("00000", graze)); + yield; + } +} + +task TValueDisplay(){ + + let objPIVNum = ObjText_Create(); + ObjText_SetFontSize(objPIVNum, 45); + ObjText_SetFontBold(objPIVNum, true); + ObjText_SetFontType(objPIVNum, "Origami Mommy"); + ObjText_SetFontColorTop(objPIVNum,0xFFFFFF); + ObjText_SetFontColorBottom(objPIVNum,0xFFFFFF); + ObjText_SetFontBorderType(objPIVNum, BORDER_FULL); + ObjText_SetFontBorderColor(objPIVNum, 0xDC47C8); + ObjText_SetFontBorderWidth(objPIVNum, 4); + ObjText_SetHorizontalAlignment(objPIVNum, ALIGNMENT_LEFT); + //ObjText_SetFontWeight(objPIVNum, 1000); + Obj_SetRenderPriorityI(objPIVNum, 2); + //ObjText_SetSidePitch(objPIVNum, -3); + ObjRender_SetPosition(objPIVNum, 1440, 275, 0); + // DEBUG + //Obj_SetVisible(objPIV, false); + + int value = 0; + + while(true){ + value = min(GetCommonDataPtr(pointerPIV, 10000), 9999999990); + //PIVMultiplierValue = value/1000; + let yass = vtos("-5.2f", value/10000); + if(value < 100000){ObjText_SetText(objPIVNum, yass ~ "[font size=25 ox=-24 oy=18]x");} + else{ObjText_SetText(objPIVNum, yass ~ "[font size=25 oy=18]x");} + yield; + } + +} + +//---------------------------------------------------- +//残機表示 +//---------------------------------------------------- +/*task TPlayerLife +{ + let lifenum = ObjText_Create(); + ObjText_SetFontSize(lifenum, 22); + ObjText_SetFontBold(lifenum, false); + ObjText_SetFontType(lifenum, "Unispace"); + ObjText_SetFontColorTop(lifenum,255,255,255); + ObjText_SetFontColorBottom(lifenum,255,255,255); + Obj_SetRenderPriorityI(lifenum, 1); + ObjRender_SetX(lifenum,507); + ObjRender_SetY(lifenum,101); + + while(true){ + let liferemain = GetPlayerLife(); + + ObjText_SetText(lifenum, rtos("00", liferemain)); + yield; + } +}*/ + +//---------------------------------------------------- +//残スペル表示 +//---------------------------------------------------- +task TPlayerSpell +{ + let spellnum = ObjText_Create(); + ObjText_SetFontSize(spellnum, 22); + ObjText_SetFontBold(spellnum, false); + ObjText_SetFontType(spellnum, "Unispace"); + ObjText_SetFontColorTop(spellnum,255,255,255); + ObjText_SetFontColorBottom(spellnum,255,255,255); + Obj_SetRenderPriorityI(spellnum, 1); + ObjRender_SetX(spellnum,offsetX); + ObjRender_SetY(spellnum,baseY+spaceY*3); + + while(true){ + let spellremain = GetPlayerSpell(); + + ObjText_SetText(spellnum, rtos("00", spellremain)); + yield; + } +} + +// New life task +task LifeDisplay(){ + +// oh god oh no + let liferemain; + let lifecounter = ObjPrim_Create(OBJ_SPRITE_LIST_2D); + let lifeshow = graphicimg; + Obj_SetRenderPriorityI(lifecounter, 79); + ObjPrim_SetTexture(lifecounter, lifeshow); + //ObjSpriteList2D_SetSourceRect(lifecounter, 256, 0, 384, 128); + //ObjRender_SetScaleXYZ(lifecounter, 0.5, 0.5, 1); + //ObjSpriteList2D_SetDestCenter(lifecounter); + + int maxText = CreateTextObject( + 1440, 390, 45, + "ASCENSION", "Origami Mommy", + 0x280644, 0x701582, + 0xD1B4FF, 3.5, + 2 + ); + + ObjText_SetFontWeight(maxText, 1000); + + int MaxLife = GetCommonData("Life Limit", 99999); + + loop{ + SetPlayerLife(min(MaxLife, GetPlayerLife())); + + if(GetPlayerY() < GetStgFrameHeight() * 1/8){ + ObjRender_SetAlpha(lifecounter, 125); + } + else{ObjRender_SetAlpha(lifecounter, 255);} + + ObjSpriteList2D_ClearVertexCount(lifecounter); + ObjSpriteList2D_SetSourceRect(lifecounter, 608, 288, 640, 288+32); + ObjRender_SetTextureFilterMag(lifecounter, FILTER_NONE); + ObjSpriteList2D_SetDestCenter(lifecounter); + ObjRender_SetScaleXYZ(lifecounter, 2, 2, 1); + liferemain = GetPlayerLife(); + ascent(i in 0..liferemain){ + ObjRender_SetPosition(lifecounter, 710+i*24, 30, 0); + ObjSpriteList2D_AddVertex(lifecounter); + } + yield; + } + +} +// New spell task +task SpellDisplay{ + + int text = CreateTextObject( + 1820, 380, 32, + "MAX", "Origami Mommy", + 0xFFB4F7, 0xFFFFFF, + 0x6600BE, 4, + 2 + ); + + Obj_SetVisible(text, false); + ObjText_SetSidePitch(text, -4); + ObjText_SetHorizontalAlignment(text, ALIGNMENT_CENTER); + + let spellremain; + let spellcounter = ObjPrim_Create(OBJ_SPRITE_LIST_2D); + let spellshow = graphicimg; + Obj_SetRenderPriorityI(spellcounter, 1); + ObjPrim_SetTexture(spellcounter, spellshow); + + loop{ + if(GetPlayerSpell() > 5){SetPlayerSpell(5);} + if(GetPlayerSpell() == 5){Obj_SetVisible(text, true);} + else{Obj_SetVisible(text, false);} + ObjSpriteList2D_ClearVertexCount(spellcounter); + ObjSpriteList2D_SetSourceRect(spellcounter, 640, 128, 768, 256); + ObjSpriteList2D_SetDestCenter(spellcounter); + ObjRender_SetScaleXYZ(spellcounter, 0.3*scale, 0.3*scale, 1); + spellremain = GetPlayerSpell(); + ascent(i in 0..spellremain){ + ObjRender_SetPosition(spellcounter, 1604+i*32, 392, 0); + ObjSpriteList2D_AddVertex(spellcounter); + } + yield; + } +} +//---------------------------------------------------- +// Edited ExRumia system +//---------------------------------------------------- +task TBossLife + +// Lifebar starts at x = 352, ends at x = 925 +{ + let path = lifebarimg; + let obj = ObjPrim_Create(OBJ_SPRITE_LIST_2D); + let objStar = ObjPrim_Create(OBJ_SPRITE_LIST_2D); + let objDivision = ObjPrim_Create(OBJ_SPRITE_LIST_2D); + let objLifebar = ObjPrim_Create(OBJ_SPRITE_LIST_2D); + //bool BossExist = false; + + ObjPrim_SetTexture(obj, path); + Obj_SetRenderPriorityI(obj, 72); + ObjRender_SetAlpha(obj, 255); + + ObjPrim_SetTexture(objStar, path); + Obj_SetRenderPriorityI(objStar, 70); + + ObjPrim_SetTexture(objDivision, path); + Obj_SetRenderPriorityI(objDivision, 72); + + ObjPrim_SetTexture(objLifebar, path); + Obj_SetRenderPriorityI(objLifebar, 70); + ObjRender_SetAlpha(objLifebar, 140); + //Obj_SetVisible(objLifebar, false); + + let lastRemStep = -1; + let lifeRateRender = 0; + + let objScene = ID_INVALID; + loop + { + objScene = GetEnemyBossSceneObjectID(); + ObjSpriteList2D_ClearVertexCount(obj); + ObjSpriteList2D_ClearVertexCount(objLifebar); + ObjSpriteList2D_ClearVertexCount(objStar); + ObjSpriteList2D_ClearVertexCount(objDivision); + if(objScene != ID_INVALID) + { + //BossExist = true; + ObjSpriteList2D_SetSourceRect(objLifebar, 8, 6, 801, 50); + ObjSpriteList2D_SetDestCenter(objLifebar); + ObjRender_SetScaleXYZ(objLifebar, 1.12, 1.25, 1); + ascent (i in 0..1){ + ObjRender_SetPosition(objLifebar, 455, 40, 1); + ObjSpriteList2D_AddVertex(objLifebar); + } + RenderActiveLife(); + + } + yield; + } + + /*task RenderLifebar(){ + ObjSprite2D_SetSourceRect(objLifebar, 5, 5, 534, 34); + ObjSprite2D_SetDestCenter(objLifebar); + ObjRender_SetPosition(objLifebar, 352, 20, 1); + while(BossExist){ + Obj_SetVisible(objLifebar, true); + yield; + } + }*/ + + function RenderActiveLife() + { + //残りステップ + let countRemStep = ObjEnemyBossScene_GetInfo(objScene, INFO_REMAIN_STEP_COUNT); + if(lastRemStep != countRemStep) + { + //ステップが変化 + lifeRateRender = 0; + } + + //Overall active life + let lifeTotalMax = ObjEnemyBossScene_GetInfo(objScene, INFO_ACTIVE_STEP_TOTAL_MAX_LIFE); + let lifeTotal = ObjEnemyBossScene_GetInfo(objScene, INFO_ACTIVE_STEP_TOTAL_LIFE); + let lifeRate = min(lifeTotal / lifeTotalMax, lifeRateRender); + ObjSpriteList2D_SetSourceRect(obj, 7, 119, 800, 159); + ObjSpriteList2D_SetDestRect(obj, 11, 20, 12 + (890-2) * lifeRate, 60); + ObjRender_SetColorHSV(obj, -60, 384, 384); + ObjSpriteList2D_AddVertex(obj); + ObjRender_SetBlendType(obj, BLEND_ALPHA); + + //Life "division" bar + ObjSpriteList2D_SetSourceRect(objDivision, 8, 56, 27, 111); + //ObjRender_SetColorHSV(objDivision, 32, 255, 255); + let listLifeDiv = [0] ~ ObjEnemyBossScene_GetInfo(objScene, INFO_ACTIVE_STEP_LIFE_RATE_LIST); + ascent(iDiv in 1 .. length(listLifeDiv)-1) + { + let rate = listLifeDiv[iDiv]; + let x = (GetStgFrameWidth()) * 0.98 * (1-rate); + ObjSpriteList2D_SetDestRect(objDivision, x-4, 62, x+24, 118); + ObjSpriteList2D_AddVertex(objDivision); + } + + //Boss star rendering + ObjRender_SetScaleXYZ(objStar, 0.6, 0.6, 1); + ObjSpriteList2D_SetSourceRect(objStar, 0, 169, 268, 430); + Obj_SetRenderPriority(objStar, 1); + ascent(iStep in 0 .. countRemStep) + { + ObjRender_SetPosition(objStar, GetStgFrameWidth()*1.6, 35+45*iStep, 1); + ObjSpriteList2D_SetDestCenter(objStar); + ObjSpriteList2D_AddVertex(objStar); + } + + lifeRateRender += 0.01; + lifeRateRender = min(lifeRateRender, 1); + lastRemStep = countRemStep; + + if(GetCommonData("IsFightingBoss", false) == true){ + if(ObjMove_GetY(GetPlayerObjectID()) < GetStgFrameHeight()/6){ + ObjRender_SetAlpha(obj, 60); + ObjRender_SetAlpha(objLifebar, 30); + } + else{ + ObjRender_SetAlpha(obj, 255); + ObjRender_SetAlpha(objLifebar, 140); + } + } + + else{ + ObjRender_SetAlpha(obj, 0); + ObjRender_SetAlpha(objLifebar, 0); + } + + } +} + +//---------------------------------------------------- +//タイマー表示 +//---------------------------------------------------- +task TBossTimer +{ + let textTimer = ObjText_Create(); + ObjText_SetFontSize(textTimer, 20); + ObjText_SetFontType(textTimer, "GravityRegular5"); + + //ObjText_SetMaxWidth(textTimer, GetStgFrameWidth()/6); + ObjText_SetHorizontalAlignment(textTimer, ALIGNMENT_LEFT); + + ObjText_SetFontBold(textTimer, true); + ObjText_SetFontColorTop(textTimer, 0xFFFFFF); + ObjText_SetFontColorBottom(textTimer, 0xFFFFFF); + ObjText_SetFontBorderType(textTimer, BORDER_FULL); + ObjText_SetFontBorderColor(textTimer, 0x45A6FF); + ObjText_SetFontBorderWidth(textTimer, 5); + Obj_SetRenderPriorityI(textTimer, 73); + //ObjRender_SetX(textTimer, GetStgFrameWidth()/2); + ObjRender_SetX(textTimer, 710); + ObjRender_SetY(textTimer, 125); + Obj_SetVisible(textTimer, true); + + let pathDigit = GetCurrentScriptDirectory() ~ "img/Default_SystemDigit.png"; + + let obj = ObjPrim_Create(OBJ_SPRITE_LIST_2D); + ObjPrim_SetTexture(obj, lifebarimg); + ObjRender_SetBlendType(obj, BLEND_ADD_RGB); + Obj_SetRenderPriority(obj, 0.75); + //ObjRender_SetY(obj, 38); + let count = 2; + + let objScene = ID_INVALID; + loop + { + objScene = GetEnemyBossSceneObjectID(); + ObjSpriteList2D_ClearVertexCount(obj); + if(objScene != ID_INVALID) + { + Obj_SetVisible(textTimer, true); + RenderTimer(); + } + else{Obj_SetVisible(textTimer, false); + } + yield; + } + + task RenderTimer() + { + let timer = ObjEnemyBossScene_GetInfo(objScene, INFO_TIMERF)/60; + timer = min(timer, 999.99); + ObjText_SetText(textTimer, rtos("000.00", timer) ~ "[font sz=15 oy=18]s LEFT"); + ObjSpriteList2D_SetSourceRect(obj, 404, 225, 537, 374); + ObjRender_SetScaleXYZ(obj, 1, 1, 1); + ObjSpriteList2D_SetDestCenter(obj); + ObjRender_SetPosition(textTimer, 590, 55, 1); + //ObjSpriteList2D_AddVertex(obj); + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) <= 10 && ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) > 0){ + if(ObjEnemyBossScene_GetInfo(objScene, INFO_TIMERF) % 60 == 0 || ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER) < 1){_Timeout();} + ObjText_SetFontBorderColor(textTimer, 0xF0396C); + } + else{ObjText_SetFontBorderColor(textTimer, 0x45A6FF); ObjText_SetFontSize(textTimer, 35);} + if(ObjMove_GetY(GetPlayerObjectID()) < GetStgFrameHeight()/8){ + ObjRender_SetAlpha(textTimer, 60); + } + else{ + ObjRender_SetAlpha(textTimer, 255); + } + yield; + } + + task _Timeout(){ // HOLY FUCK THE TIMER IS RUNNING OUT BITCH + + ascent(i in 0..30){ + ObjText_SetFontSize(textTimer, Interpolate_Decelerate(50, 25, i/30)); + //ObjRender_SetScaleXYZ(obj, Interpolate_Decelerate(0.6, 0.38, i/30)); + yield; + } + + } +} + +task TScoreAward(dascore){ + + let objText = ObjText_Create(); + int x = rand_int(0, 99); + + RegularAward; + + task RegularAward{ + + let fontsizearray = [70, 70, 70, 65, 60, 65, 70, 70, 70, 40, 40]; + let textarray = ["So Cool Bestie!", "Bimbo Eliminated!", "Wig Snatched!", "Neutralized Boss Sexiness!", "Gay Rights Confirmed!", "Himbo Kisses!", "Slay Button Hit!", "Yass!!!!", "Gatekept, Gaslit, Girlbossed!", "Spell Card Capture!"]; + + int y = rand_int(0, length(textarray)-2); + + ObjText_SetText(objText, textarray[y]); // Selects a random capture text from the array + ObjText_SetFontSize(objText, fontsizearray[y]*1.5); + ObjText_SetFontType(objText, "Exotc350 DmBd BT"); + + //ObjText_SetMaxWidth(objText, GetStgFrameWidth()); + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER); + + ObjText_SetFontBold(objText, true); + ObjText_SetFontColorTop(objText, 0xFFD34D); + ObjText_SetFontColorBottom(objText, 0xFFF2CA); + ObjText_SetFontBorderType(objText, BORDER_FULL); + ObjText_SetFontBorderColor(objText,0, 0, 0); + ObjText_SetFontBorderWidth(objText, 3); + Obj_SetRenderPriority(objText, 0.6); + ObjRender_SetX(objText, GetStgFrameWidth()/2); + ObjRender_SetY(objText, GetStgFrameHeight()/5); + } + + let scorefinal = trunc(dascore/10) * 10; + let scorescene = GetEnemyBossSceneObjectID(); + + if (ObjEnemyBossScene_GetInfo(scorescene, INFO_PLAYER_SHOOTDOWN_COUNT) == 0 && + ObjEnemyBossScene_GetInfo(scorescene, INFO_PLAYER_SPELL_COUNT) == 0){ + AddScore(scorefinal); + } + + let strScore = "Capture Bonus +" ~ DigitToCommaArray(scorefinal); + let objScore = ObjText_Create(); + ObjText_SetText(objScore, strScore); + ObjText_SetFontSize(objScore, 85); + ObjText_SetFontType(objScore, "Anke Calligraph"); + + ObjText_SetMaxWidth(objScore, GetStgFrameWidth()); + ObjText_SetHorizontalAlignment(objScore, ALIGNMENT_CENTER); + + ObjText_SetFontBold(objScore, true); + ObjText_SetFontColorTop(objScore, 0x9C2400); + ObjText_SetFontColorBottom(objScore, 0xFF982A); + ObjText_SetFontBorderType(objScore, BORDER_FULL); + ObjText_SetFontBorderColor(objScore, 255, 255, 255); + ObjText_SetFontBorderWidth(objScore, 3); + Obj_SetRenderPriority(objScore, 0.6); + ObjRender_SetX(objScore, GetStgFrameWidth()/2 - (GetStgFrameWidth()/2-5)); + ObjRender_SetY(objScore, GetStgFrameHeight()/3.2-15); + + wait(120); + + Obj_Delete(objText); + Obj_Delete(objScore); + +} +//---------------------------------------------------- +//FPS表示 +//---------------------------------------------------- +task TCurrentFps() +{ + + if(IsReplay()){return;} + + let objText = ObjText_Create(); + ObjText_SetFontSize(objText, 36); + ObjText_SetFontBold(objText, true); + ObjText_SetFontType(objText, "Unispace"); + ObjText_SetFontColorTop(objText, 0x6747FF); + ObjText_SetFontColorBottom(objText, 0xAEC4FF); + ObjText_SetFontBorderType(objText, BORDER_FULL); + ObjText_SetFontBorderColor(objText, 38, 3, 93); + ObjText_SetFontBorderWidth(objText, 1.5); + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_RIGHT); + ObjText_SetMaxWidth(objText, GetScreenWidth() - 8); + Obj_SetRenderPriority(objText, 1.0); + ObjRender_SetX(objText, 0); + ObjRender_SetY(objText, GetScreenHeight() - 48); + + loop + { + let fps = GetCurrentFps(); + let text = vtos("1.2f", fps) ~ "fps"; + ObjText_SetText(objText, text); + yield; + } +} + +task TReplayFps() +{ + if(!IsReplay()){return;} + + let objText = ObjText_Create(); + ObjText_SetFontSize(objText, 36); + ObjText_SetFontType(objText, "Unispace"); + ObjText_SetFontBold(objText, true); + ObjText_SetFontColorTop(objText, 128, 128, 255); + ObjText_SetFontColorBottom(objText, 255, 255, 255); + ObjText_SetFontBorderType(objText, BORDER_FULL); + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_RIGHT); + ObjText_SetFontBorderColor(objText,38, 3, 93); + ObjText_SetFontBorderWidth(objText, 1); + Obj_SetRenderPriorityI(objText, 79); + + let px = GetStgFrameWidth() - 10; + let py = GetStgFrameHeight() - 42; + ObjRender_SetX(objText, px); + ObjRender_SetY(objText, py); + + loop + { + let fps = GetReplayFps(); + let text = vtos("1.2f", fps); + ObjText_SetText(objText, "REPLAY MODE: " ~ text ~ "fps"); + yield; + } +} + +//---------------------------------------------------- +//ユーティリティ +//---------------------------------------------------- diff --git a/script/KevinSystem/PlayerSFX/CK Music Factory/air01.wav b/script/KevinSystem/PlayerSFX/CK Music Factory/air01.wav new file mode 100644 index 0000000..bc2c0ed Binary files /dev/null and b/script/KevinSystem/PlayerSFX/CK Music Factory/air01.wav differ diff --git a/script/KevinSystem/PlayerSFX/CK Music Factory/air02.wav b/script/KevinSystem/PlayerSFX/CK Music Factory/air02.wav new file mode 100644 index 0000000..f7e5ed8 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/CK Music Factory/air02.wav differ diff --git a/script/KevinSystem/PlayerSFX/CK Music Factory/laser01.wav b/script/KevinSystem/PlayerSFX/CK Music Factory/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/CK Music Factory/laser01.wav differ diff --git a/script/KevinSystem/PlayerSFX/CK Music Factory/slash01.wav b/script/KevinSystem/PlayerSFX/CK Music Factory/slash01.wav new file mode 100644 index 0000000..364dfca Binary files /dev/null and b/script/KevinSystem/PlayerSFX/CK Music Factory/slash01.wav differ diff --git a/script/KevinSystem/PlayerSFX/CK Music Factory/wind01.wav b/script/KevinSystem/PlayerSFX/CK Music Factory/wind01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/CK Music Factory/wind01.wav differ diff --git a/script/KevinSystem/PlayerSFX/TAM Music Factory/se04.wav b/script/KevinSystem/PlayerSFX/TAM Music Factory/se04.wav new file mode 100644 index 0000000..ca33890 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/TAM Music Factory/se04.wav differ diff --git a/script/KevinSystem/PlayerSFX/TAM Music Factory/status4.wav b/script/KevinSystem/PlayerSFX/TAM Music Factory/status4.wav new file mode 100644 index 0000000..1227a08 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/TAM Music Factory/status4.wav differ diff --git a/script/KevinSystem/PlayerSFX/TAM Music Factory/tama2.wav b/script/KevinSystem/PlayerSFX/TAM Music Factory/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/KevinSystem/PlayerSFX/TAM Music Factory/tama2.wav differ diff --git a/script/KevinSystem/PlayerSFX/ZaGames_PlayerFire1.wav b/script/KevinSystem/PlayerSFX/ZaGames_PlayerFire1.wav new file mode 100644 index 0000000..f5406bf Binary files /dev/null and b/script/KevinSystem/PlayerSFX/ZaGames_PlayerFire1.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_Base.wav b/script/KevinSystem/PlayerSFX/bfxr_Base.wav new file mode 100644 index 0000000..15e3f00 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_Base.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_Base2.wav b/script/KevinSystem/PlayerSFX/bfxr_Base2.wav new file mode 100644 index 0000000..dff783c Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_Base2.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_Base3.wav b/script/KevinSystem/PlayerSFX/bfxr_Base3.wav new file mode 100644 index 0000000..6cfced3 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_Base3.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_BombOld.wav b/script/KevinSystem/PlayerSFX/bfxr_BombOld.wav new file mode 100644 index 0000000..327dbb5 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_BombOld.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_Burn.wav b/script/KevinSystem/PlayerSFX/bfxr_Burn.wav new file mode 100644 index 0000000..6c241e4 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_Burn.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_ExplosionMini.wav b/script/KevinSystem/PlayerSFX/bfxr_ExplosionMini.wav new file mode 100644 index 0000000..d24862e Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_ExplosionMini.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_Graze.wav b/script/KevinSystem/PlayerSFX/bfxr_Graze.wav new file mode 100644 index 0000000..4c662e6 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_Graze.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_LaserActivate.wav b/script/KevinSystem/PlayerSFX/bfxr_LaserActivate.wav new file mode 100644 index 0000000..321befd Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_LaserActivate.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_LaserDeactivate.wav b/script/KevinSystem/PlayerSFX/bfxr_LaserDeactivate.wav new file mode 100644 index 0000000..2a05c53 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_LaserDeactivate.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_MissileExplode.wav b/script/KevinSystem/PlayerSFX/bfxr_MissileExplode.wav new file mode 100644 index 0000000..243de5e Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_MissileExplode.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_PlayerHit.wav b/script/KevinSystem/PlayerSFX/bfxr_PlayerHit.wav new file mode 100644 index 0000000..971a3b1 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_PlayerHit.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_PlayerShootdown.wav b/script/KevinSystem/PlayerSFX/bfxr_PlayerShootdown.wav new file mode 100644 index 0000000..8efe834 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_PlayerShootdown.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_ScytheRetrieve.wav b/script/KevinSystem/PlayerSFX/bfxr_ScytheRetrieve.wav new file mode 100644 index 0000000..99b3040 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_ScytheRetrieve.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_Shine.wav b/script/KevinSystem/PlayerSFX/bfxr_Shine.wav new file mode 100644 index 0000000..5b16d6d Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_Shine.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_Splash.wav b/script/KevinSystem/PlayerSFX/bfxr_Splash.wav new file mode 100644 index 0000000..6a4d49d Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_Splash.wav differ diff --git a/script/KevinSystem/PlayerSFX/laser01.wav b/script/KevinSystem/PlayerSFX/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/laser01.wav differ diff --git a/script/KevinSystem/PlayerSFX/magic21.wav b/script/KevinSystem/PlayerSFX/magic21.wav new file mode 100644 index 0000000..19714fe Binary files /dev/null and b/script/KevinSystem/PlayerSFX/magic21.wav differ diff --git a/script/KevinSystem/PlayerSFX/retrolaser.wav b/script/KevinSystem/PlayerSFX/retrolaser.wav new file mode 100644 index 0000000..bb38c6d Binary files /dev/null and b/script/KevinSystem/PlayerSFX/retrolaser.wav differ diff --git a/script/KevinSystem/PlayerSFX/retrolaser2.wav b/script/KevinSystem/PlayerSFX/retrolaser2.wav new file mode 100644 index 0000000..e592960 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/retrolaser2.wav differ diff --git a/script/KevinSystem/PlayerSFX/se_nep00.wav b/script/KevinSystem/PlayerSFX/se_nep00.wav new file mode 100644 index 0000000..32b0608 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/se_nep00.wav differ diff --git a/script/KevinSystem/PlayerSFX/se_old_kira01.wav b/script/KevinSystem/PlayerSFX/se_old_kira01.wav new file mode 100644 index 0000000..9f5835a Binary files /dev/null and b/script/KevinSystem/PlayerSFX/se_old_kira01.wav differ diff --git a/script/KevinSystem/PlayerSFX/slash01.wav b/script/KevinSystem/PlayerSFX/slash01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/slash01.wav differ diff --git a/script/KevinSystem/PlayerSFX/tama2.wav b/script/KevinSystem/PlayerSFX/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/KevinSystem/PlayerSFX/tama2.wav differ diff --git a/script/KevinSystem/PlayerSoundLib.dnh b/script/KevinSystem/PlayerSoundLib.dnh new file mode 100644 index 0000000..a93dc7b --- /dev/null +++ b/script/KevinSystem/PlayerSoundLib.dnh @@ -0,0 +1,66 @@ +// Sound effects for player scripts go here. + + +// Link to sound folder + +//let sddir = GetCurrentScriptDirectory() ~ "./PlayerSFX"; + +string[] SFXList = GetFilePathList("script/KevinSystem/PlayerSFX/"); + +let SFXVol = GetAreaCommonData("Config", "SEVol", 100) * 0.01; + +const Base1 = ObjSound_Create(), +Base2 = ObjSound_Create(), +Base3 = ObjSound_Create(), +Bomb1 = ObjSound_Create(), +Fire = ObjSound_Create(), +Explosion1 = ObjSound_Create(), +Graze = ObjSound_Create(), +LaserAct = ObjSound_Create(), +LaserDeact = ObjSound_Create(), +Explosion2 = ObjSound_Create(), +PlayerHit = ObjSound_Create(), +PlayerDie = ObjSound_Create(), +Misc1 = ObjSound_Create(), +Shine = ObjSound_Create(), +Splash = ObjSound_Create(), +PlayerDie2 = ObjSound_Create(), +Misc2 = ObjSound_Create(), +Base4 = ObjSound_Create(), +Bomb2 = ObjSound_Create(), +MasterSpark = ObjSound_Create(), +Misc3 = ObjSound_Create(), +Base5 = ObjSound_Create(); + +let VarList = [Base1, Base2, Base3, Bomb1, Fire, Explosion1, Graze, LaserAct, LaserDeact, Explosion2, PlayerHit, PlayerDie, Misc1, Shine, Splash, PlayerDie2, Misc2, Base4, Bomb2, MasterSpark, Misc3, Base5]; +let VolList = [40, 40, 40, 40, 40, 40, 40, 40, 40, 80, 80, 80, 40, 80, 40, 80, 40, 40, 40, 40, 40, 40]; + +// Function for loading and setting volume of a sound object + +task _Init(){ + +} + +function LoadEx(obj, targetpath, targetvol){ + + //int obj = ObjSound_Create(); + ObjSound_Load(obj, targetpath); + ObjSound_SetVolumeRate(obj, targetvol * SFXVol); + ObjSound_SetSoundDivision(obj, SOUND_SE); + + //return obj; + +} + +task _SoundTask(){ + + int i = 0; + + WriteLog("File being read is " ~ SFXList[0]); + + for each(var objSound in ref VarList){ + LoadEx(objSound, SFXList[i], 25); + i++; + } + +} diff --git a/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItem1.wav b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItem1.wav new file mode 100644 index 0000000..b616c81 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItem1.wav differ diff --git a/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItemCancel.wav b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItemCancel.wav new file mode 100644 index 0000000..b37096c Binary files /dev/null and b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItemCancel.wav differ diff --git a/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItemSpecial.wav b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItemSpecial.wav new file mode 100644 index 0000000..5b16d6d Binary files /dev/null and b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItemSpecial.wav differ diff --git a/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItemSpecialOLD.wav b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItemSpecialOLD.wav new file mode 100644 index 0000000..df2bfa3 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItemSpecialOLD.wav differ diff --git a/script/KevinSystem/RyannSFX/ItemSFX/bfxr_LifeExtend.wav b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_LifeExtend.wav new file mode 100644 index 0000000..f58d225 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_LifeExtend.wav differ diff --git a/script/KevinSystem/RyannSFX/ItemSFX/bfxr_SpellExtend.wav b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_SpellExtend.wav new file mode 100644 index 0000000..5978006 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_SpellExtend.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_alert.wav b/script/KevinSystem/RyannSFX/ryannlib/se_alert.wav new file mode 100644 index 0000000..ebf26bd Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_alert.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_boon00.wav b/script/KevinSystem/RyannSFX/ryannlib/se_boon00.wav new file mode 100644 index 0000000..319c8db Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_boon00.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_ch01.wav b/script/KevinSystem/RyannSFX/ryannlib/se_ch01.wav new file mode 100644 index 0000000..6026daf Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_ch01.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_ch02.wav b/script/KevinSystem/RyannSFX/ryannlib/se_ch02.wav new file mode 100644 index 0000000..705ef78 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_ch02.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_don00.wav b/script/KevinSystem/RyannSFX/ryannlib/se_don00.wav new file mode 100644 index 0000000..4a7a943 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_don00.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_explode.wav b/script/KevinSystem/RyannSFX/ryannlib/se_explode.wav new file mode 100644 index 0000000..ac1bc44 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_explode.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_extend.wav b/script/KevinSystem/RyannSFX/ryannlib/se_extend.wav new file mode 100644 index 0000000..a8b25c6 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_extend.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_extend2.wav b/script/KevinSystem/RyannSFX/ryannlib/se_extend2.wav new file mode 100644 index 0000000..23c7e4a Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_extend2.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_graze.wav b/script/KevinSystem/RyannSFX/ryannlib/se_graze.wav new file mode 100644 index 0000000..d260749 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_graze.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_kira00.wav b/script/KevinSystem/RyannSFX/ryannlib/se_kira00.wav new file mode 100644 index 0000000..db9d186 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_kira00.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_kira02.wav b/script/KevinSystem/RyannSFX/ryannlib/se_kira02.wav new file mode 100644 index 0000000..9522353 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_kira02.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_lazer00.wav b/script/KevinSystem/RyannSFX/ryannlib/se_lazer00.wav new file mode 100644 index 0000000..7c4aa4e Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_lazer00.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_lazer01.wav b/script/KevinSystem/RyannSFX/ryannlib/se_lazer01.wav new file mode 100644 index 0000000..3a1086c Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_lazer01.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_nep00.wav b/script/KevinSystem/RyannSFX/ryannlib/se_nep00.wav new file mode 100644 index 0000000..32b0608 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_nep00.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_old_extend.wav b/script/KevinSystem/RyannSFX/ryannlib/se_old_extend.wav new file mode 100644 index 0000000..23c7e4a Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_old_extend.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_old_kira00.ogg b/script/KevinSystem/RyannSFX/ryannlib/se_old_kira00.ogg new file mode 100644 index 0000000..81216bc Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_old_kira00.ogg differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_old_kira00.wav b/script/KevinSystem/RyannSFX/ryannlib/se_old_kira00.wav new file mode 100644 index 0000000..97c4696 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_old_kira00.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_old_lazer01.wav b/script/KevinSystem/RyannSFX/ryannlib/se_old_lazer01.wav new file mode 100644 index 0000000..57929ef Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_old_lazer01.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_old_nep00.wav b/script/KevinSystem/RyannSFX/ryannlib/se_old_nep00.wav new file mode 100644 index 0000000..5b4acb2 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_old_nep00.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_pause.wav b/script/KevinSystem/RyannSFX/ryannlib/se_pause.wav new file mode 100644 index 0000000..1674d67 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_pause.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_select00.wav b/script/KevinSystem/RyannSFX/ryannlib/se_select00.wav new file mode 100644 index 0000000..36b6dab Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_select00.wav differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_slash.ogg b/script/KevinSystem/RyannSFX/ryannlib/se_slash.ogg new file mode 100644 index 0000000..19beee1 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_slash.ogg differ diff --git a/script/KevinSystem/RyannSFX/ryannlib/se_tan00.wav b/script/KevinSystem/RyannSFX/ryannlib/se_tan00.wav new file mode 100644 index 0000000..7ba4311 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ryannlib/se_tan00.wav differ diff --git a/script/KevinSystem/SoundName.txt b/script/KevinSystem/SoundName.txt new file mode 100644 index 0000000..46ce60e --- /dev/null +++ b/script/KevinSystem/SoundName.txt @@ -0,0 +1 @@ +PLAYER SOUND NAME diff --git a/script/KevinSystem/TerraShot2x/shot_1.png b/script/KevinSystem/TerraShot2x/shot_1.png new file mode 100644 index 0000000..8665605 Binary files /dev/null and b/script/KevinSystem/TerraShot2x/shot_1.png differ diff --git a/script/KevinSystem/TerraShot2x/shot_const.dnh b/script/KevinSystem/TerraShot2x/shot_const.dnh new file mode 100644 index 0000000..a900147 Binary files /dev/null and b/script/KevinSystem/TerraShot2x/shot_const.dnh differ diff --git a/script/KevinSystem/TerraShot2x/shot_data_1.dnh b/script/KevinSystem/TerraShot2x/shot_data_1.dnh new file mode 100644 index 0000000..82ed25b Binary files /dev/null and b/script/KevinSystem/TerraShot2x/shot_data_1.dnh differ diff --git a/script/KevinSystem/Universal_EnemyLib.dnh b/script/KevinSystem/Universal_EnemyLib.dnh new file mode 100644 index 0000000..8e12311 --- /dev/null +++ b/script/KevinSystem/Universal_EnemyLib.dnh @@ -0,0 +1,890 @@ +/* + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// + + UNIVERSAL LIBRARY FOR ENEMY-RELATED FUNCTIONS + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// + +*/ + +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" + +// Code by Kevinmonitor with some assistance. +/* + +///////////// ENEMY SPAWNING DURING STAGES ///////////// + +*/ + +function _InitDifficulty(int diffInt){ + + int difficulty = 0; + + if(GetCommonData("Difficulty", "Normal") == "Normal"){ + difficulty = 0; + } + + else if(GetCommonData("Difficulty", "Normal") == "Hard"){ + difficulty = 1; + } + + else if(GetCommonData("Difficulty", "Normal") == "Lunatic"){ + difficulty = 2; + } + + return difficulty; +} + +// Explosion Sound Effects + +task _RenderBoss(int enemy){ + + int aniidle = 0; + + string tex = "script/game/resourceLib/Spritesheet_StationJam.png"; + + //LoadTextureEx(tex, true, true); + + ObjPrim_SetTexture(enemy, tex); + ObjSprite2D_SetSourceRect(enemy, 1280, 0, 1280+256, 256); + ObjSprite2D_SetDestCenter(enemy); + ObjRender_SetScaleXYZ(enemy, 1); + + int nameText = CreateTextObject( + GetStgFrameWidth()*0.3, 200, 25, + "REMILIA SCARLET", "Origami Mommy", + 0xFF5A5A, 0xFFFFFF, + 0x791D1D, 3, + 1 + ); + + ObjRender_SetAngleZ(nameText, -90); + ObjText_SetFontBold(nameText, true); + + //_BossMarker(enemy, tex, 512, 0, 768, 256, 0.45, 30); + + while(!Obj_IsDeleted(enemy)){ + + yield; + + } +} + +task _RenderMidboss(int enemy){ + + int aniidle = 0; + + string tex = "script/game/StageLib/BossAsset.png"; + + LoadTextureEx(tex, true, true); + + int nameText = CreateTextObject( + GetStgFrameWidth()*0.38, 10, 42, + "MIDBOSS: Kobiko", "Connecting Chain Handserif", + 0xBA8AFF, 0xFFFFFF, + 0x552A9C, 3, + 1 + ); + + ObjText_SetFontBold(nameText, true); + ObjPrim_SetTexture(enemy, tex); + ObjSprite2D_SetSourceRect(enemy, 768, 0, 768+512, 512); + ObjSprite2D_SetDestCenter(enemy); + ObjRender_SetScaleXYZ(enemy, 0.5); + + _BossMarker(enemy, tex, 512, 256, 768, 512, 0.45, 30); + + while(!Obj_IsDeleted(enemy)){ + + yield; + + } +} + +task _FadeInSpawn( + int enemyID, + float spawnX, float spawnY, + float destX, float destY, + float spawnScale, float destScale, + int time){ + + ObjMove_SetPosition(enemyID, spawnX, spawnY); + ObjRender_SetAlpha(enemyID, 0); + + ObjMove_SetDestAtFrame(enemyID, destX, destY, time, LERP_DECELERATE); + + ascent(i in 0..time){ + ObjRender_SetAlpha(enemyID, Interpolate_Decelerate(0, 255, i/time)); + ObjRender_SetScaleXYZ(enemyID, Interpolate_Decelerate(spawnScale, destScale, i/time)); + yield; + } + + } + +// Creates an enemy and spawns them using _FadeInSpawn. Shooting and movement tasks not covered. +// Task also handles deleting the enemy after their life reaches 0. + +/* +BhestieBlue: 0, 0, 256, 256 +BhestieGreen: 256, 0, 512, 256 +GaySamoyed: 0, 256, 256, 512 +EvilSamoyed: 256, 256, 512, 512 +*/ + +function _CreateEnemy( + float spawnX, float spawnY, float destX, float destY, int spawntime, + float spawnScale, float destScale, + float health, float sizeHitbox, float sizeHurtbox, + texture, + int rectLeft, int rectTop, int rectRight, int rectBottom){ + + // Essentials + int enemyID = ObjEnemy_Create(OBJ_ENEMY); + ObjEnemy_Regist(enemyID); + ObjEnemy_SetLife(enemyID, health); + ObjEnemy_SetAutoDelete(enemyID, true); + + // TBA: Handle animations + ObjPrim_SetTexture(enemyID, texture); + ObjSprite2D_SetSourceRect(enemyID, rectLeft, rectTop, rectRight, rectBottom); + ObjSprite2D_SetDestCenter(enemyID); + + // Spawning + _FadeInSpawn(enemyID, spawnX, spawnY, destX, destY, spawnScale, destScale, spawntime); + _HandleEnemyWellbeing(enemyID, sizeHitbox, sizeHurtbox); + + return enemyID; + + } + +// Special overload for creating hitbox/hurtboxless enemies. + +function _CreateEnemy( + bool intersectionrender, + float spawnX, float spawnY, float destX, float destY, int spawntime, + float spawnScale, float destScale, + float health, float sizeHitbox, float sizeHurtbox, + texture, + int rectLeft, int rectTop, int rectRight, int rectBottom){ + + // Essentials + int enemyID = ObjEnemy_Create(OBJ_ENEMY); + ObjEnemy_Regist(enemyID); + ObjEnemy_SetLife(enemyID, health); + ObjEnemy_SetAutoDelete(enemyID, true); + + // TBA: Handle animations + ObjPrim_SetTexture(enemyID, texture); + ObjSprite2D_SetSourceRect(enemyID, rectLeft, rectTop, rectRight, rectBottom); + ObjSprite2D_SetDestCenter(enemyID); + + // Spawning + _FadeInSpawn(enemyID, spawnX, spawnY, destX, destY, spawnScale, destScale, spawntime); + if (intersectionrender){_HandleEnemyWellbeing(enemyID, sizeHitbox, sizeHurtbox);} + else{} + + return enemyID; + + } + + +// Hitbox and deletion + +task _HandleEnemyWellbeing(int enemyID, float sizeHitbox, float sizeHurtbox){ + + //float enmX = 0, enmY = 0; + + while(ObjEnemy_GetInfo(enemyID, INFO_LIFE) > 0){ + + ObjEnemy_SetIntersectionCircleToShot(enemyID, ObjMove_GetX(enemyID), ObjMove_GetY(enemyID), sizeHitbox); + //ObjEnemy_SetIntersectionCircleToPlayer(enemyID, ObjMove_GetX(enemyID), ObjMove_GetY(enemyID), sizeHurtbox); + yield; + + } + + Obj_Delete(enemyID); + +} + + +// Fading invincibility for bosses/enemies (with parameters for wait times and fade times, and a separate multiplier for bomb damage rate (final spells)) + +task _FadeInvincibility(int target, int waittime, int fadetime, float bombmultiplier){ + + float x = 0; + ObjEnemy_SetDamageRate(target, 0, 0); + wait(waittime); + ascent(i in 0..fadetime){ + x = Interpolate_Accelerate(0, 100, i/fadetime); + ObjEnemy_SetDamageRate(target, x, x*bombmultiplier); + yield; + } + +} + +/* +///////////// HANDLING THE END OF SINGLES (DURING BOSS/MIDBOSS FIGHTS) ///////////// + +To-do: Move item creation to the item script(s) + +*/ + +////// NEW ////// + +task _GoToBrazil( + int targetscene, targetenemy, + int maxitemdrop, int minitemdrop){ + + while(ObjEnemy_GetInfo(targetenemy, INFO_LIFE)>0){ + yield; + } + + maxitemdrop = 14; + minitemdrop = 7; + + int finalItemDrop = 0; + let itemType = POINT_RAINBOW; + + int maxTimer = ObjEnemyBossScene_GetInfo(targetscene, INFO_ORGTIMERF); + int killTimer = ObjEnemyBossScene_GetInfo(targetscene, INFO_TIMERF); + + bool isnon = ObjEnemyBossScene_GetInfo(targetscene, INFO_IS_SPELL); + + // If the boss is killed within the first 1/5 of the timer, drop full items + + if(killTimer >= maxTimer*(4/5)) {finalItemDrop = maxitemdrop;} + + // Starting from the rest of the timer, the maximum items that can be dropped is equal to 4/5 of the max drop amount + + else{finalItemDrop = Interpolate_Decelerate(minitemdrop, maxitemdrop*(4/5), killTimer/(maxTimer*4/5));} + + // If the player has lost a life, lock the number of items to the lowest possible + + if(ObjEnemyBossScene_GetInfo(targetscene, INFO_PLAYER_SHOOTDOWN_COUNT) > 0){ + finalItemDrop = minitemdrop; + //itemType = POINT_REGULAR; + } + + DeleteShotAll(TYPE_ALL,TYPE_ITEM); + + SetPlayerInvincibilityFrame(120); + + // Common Data + + NotifyEventAll(EV_SINGLE_ITEM_DROP, ObjMove_GetX(targetenemy), ObjMove_GetY(targetenemy), finalItemDrop, itemType); + + wait(120); + + float[] enemyPos = [ObjMove_GetX(targetenemy), ObjMove_GetY(targetenemy)]; + + SetCommonData("Entering PIV", GetAreaCommonData("PIV", "currentvalue", 10000)); + SetCommonData("Boss Position X", enemyPos[0]); + SetCommonData("Boss Position Y", enemyPos[1]); + + Obj_Delete(targetenemy); + +} + +////// OLD/LEGACY ////// +// Basic post-death handling after every attack (Duo). + +function _GoToBrazilDuo(targetscene, targetenemy, targetenemyA, targetenemyB, returnXA, returnYA, returnXB, returnYB, bool isnon, int itemdropamount){ + + while(ObjEnemy_GetInfo(targetenemy, INFO_LIFE) > 0){ + yield; + } + + DeleteShotAll(TYPE_ALL,TYPE_ITEM); + SetPlayerInvincibilityFrame(120); + + // returnX and returnY are the boss positions they return to at the end of every pattern. (I'm too lazy for common data...) + + ObjMove_CancelMovement(targetenemyA); ObjMove_CancelMovement(targetenemyB); + + ObjMove_SetDestAtFrame(targetenemyA, returnXA, returnYA, 45, LERP_DECELERATE); + ObjMove_SetDestAtFrame(targetenemyB, returnXB, returnYB, 45, LERP_DECELERATE); + + async{ + wait(45); + ObjMove_CancelMovement(targetenemyA); ObjMove_CancelMovement(targetenemyB); + ObjMove_SetDestAtFrame(targetenemyA, returnXA, returnYA, 15, LERP_DECELERATE); + ObjMove_SetDestAtFrame(targetenemyB, returnXB, returnYB, 15, LERP_DECELERATE); + ObjMove_SetProcessMovement(targetenemyA, false); + ObjMove_SetProcessMovement(targetenemyB, false); + return; + } + + alternative(isnon) + + case(true){_NonspellItemDrop(targetscene, targetenemyA, itemdropamount); _NonspellItemDrop(targetscene, targetenemyB, itemdropamount);} + + others{_SpellItemDrop(targetscene, targetenemyA, itemdropamount); _SpellItemDrop(targetscene, targetenemyB, itemdropamount);} + + wait(120); + + Obj_Delete(targetenemy); + Obj_Delete(targetenemyA); + Obj_Delete(targetenemyB); + +} + +// Basic post-death handling after every attack (Solo). + +task _GoToBrazil(targetscene, targetenemy, returnX, returnY, bool isnon, int itemdropamount){ + + while(ObjEnemy_GetInfo(targetenemy, INFO_LIFE)>0){ + yield; + } + + DeleteShotAll(TYPE_ALL,TYPE_ITEM); + + SetPlayerInvincibilityFrame(120); + + // ITS COMMON DATA TIME BITCHES + + float[] enemyPos = [ObjMove_GetX(targetenemy), ObjMove_GetY(targetenemy)]; + SetCommonData("Boss Position", enemyPos); + + alternative(isnon) + case(true){_NonspellItemDrop(targetscene, targetenemy, itemdropamount);} + others{_NonspellItemDrop(targetscene, targetenemy, itemdropamount);} + + wait(120); + + Obj_Delete(targetenemy); + +} + +task _GoToBrazilMidboss(targetscene, targetenemy, bool isnon, int itemdropamount){ + + while(ObjEnemy_GetInfo(targetenemy, INFO_LIFE)>0){ + yield; + } + + DeleteShotAll(TYPE_ALL,TYPE_ITEM); + + SetPlayerInvincibilityFrame(120); + + // ITS COMMON DATA TIME BITCHES + + float[] enemyPos = [ObjMove_GetX(targetenemy), ObjMove_GetY(targetenemy)]; + SetCommonData("Boss Position", enemyPos); + + alternative(isnon) + case(true){_NonspellItemDrop(targetscene, targetenemy, itemdropamount);} + others{_NonspellItemDrop(targetscene, targetenemy, itemdropamount);} + + wait(60); + + ObjMove_SetDestAtFrame(targetenemy, enemyPos[0], -150, 45, LERP_SMOOTHER); + + wait(45); + + Obj_Delete(targetenemy); + +} + +// Used after end of last spell for dramatic effect. NOTE TO SELF: REPLACE SOUND & GRAPHICAL EFFECTS + +task _ByeBitch(targetscene, targetenemy){ + + while(ObjEnemyBossScene_GetInfo(targetscene, INFO_CURRENT_LIFE) > 0){ + yield; + } + + /*ObjSound_Load(death, defeatsnd); + ObjSound_SetVolumeRate(death, 30); + ObjSound_SetFade(death, 5);*/ + + let x = ObjMove_GetX(targetenemy); + let y = ObjMove_GetY(targetenemy); + + StartSlow(TARGET_ALL, 30); + SetPlayerInvincibilityFrame(180); + DeleteShotAll(TYPE_ALL,TYPE_ITEM); + //ObjSound_Play(death); + TExplosionA(x,y,10,0.5); + wait(120); + + StopSlow(TARGET_ALL); + //ObjSound_Play(death); + //Obj_Delete(target); + TExplosionA(x,y,10,0.5); + wait(120); + +} + +function _ByeBitches(int targetscene, int targetboss, int targetenemyA, int targetenemyB, int itemdropamount){ + + //wait(120); + + loop{ + float life = ObjEnemy_GetInfo(targetboss, INFO_LIFE); + if(life > 0){yield;} + else{break;} + } + + int death = ObjSound_Create(); + ObjSound_Load(death, defeatsnd); + ObjSound_SetVolumeRate(death, 40); + ObjSound_SetFade(death, 7.5); + + StartSlow(TARGET_ALL, 30); + SetPlayerInvincibilityFrame(180); + DeleteShotAll(TYPE_ALL,TYPE_ITEM); + ObjSound_Play(death); + TExplosionA(ObjMove_GetX(targetenemyA), ObjMove_GetY(targetenemyA), 10, 0.5); + TExplosionA(ObjMove_GetX(targetenemyB), ObjMove_GetY(targetenemyB), 10, 0.5); + wait(120); + + _SpellItemDrop(targetscene, targetenemyA, itemdropamount); + _SpellItemDrop(targetscene, targetenemyB, itemdropamount); + + StopSlow(TARGET_ALL); + + ObjSound_Play(death); + + TExplosionA(ObjMove_GetX(targetenemyA), ObjMove_GetY(targetenemyA), 10, 0.5); + TExplosionA(ObjMove_GetX(targetenemyB), ObjMove_GetY(targetenemyB), 10, 0.5); + + Obj_Delete(targetboss); + Obj_Delete(targetenemyA); + Obj_Delete(targetenemyB); + + wait(120); + +} + +/* + +//////////////// GRAPHICAL/VISUAL-RELATED TASKS AND FUNCTIONS //////////////// + +*/ + +// Handles boss markers during boss fights. + +task _BossMarker(int targetenemy, markertex, int left, int top, int right, int bottom, float scale, float heightoffset){ + + int marker = ObjPrim_Create(OBJ_SPRITE_2D); + ObjPrim_SetTexture(marker, markertex); + ObjSprite2D_SetSourceRect(marker, left, top, right, bottom); + ObjSprite2D_SetDestCenter(marker); + ObjRender_SetScaleXYZ(marker, scale); + Obj_SetRenderPriorityI(marker, 19); + ObjRender_SetAlpha(marker, 255); + //ObjRender_SetY(marker, GetStgFrameHeight()+heightoffset); + + while(!Obj_IsDeleted(targetenemy)){ + ObjRender_SetPosition(marker, ObjRender_GetX(targetenemy)+(GetScreenWidth()-GetStgFrameWidth())/2, GetStgFrameHeight()+heightoffset+(GetScreenHeight()-GetStgFrameHeight())/2, 1); + yield; + } + + Obj_Delete(marker); +} + +// Tasks that handle calling a spellcard. No spell card history. + +task _DuoCutin( + image1, image2, + int rectleft, int recttop, int rectright, int rectbottom, + int spellID, string spellname, + float textsize, float bordersize, int bordercolor, int bonusbordercolor, + float textstartx, float textendx, int render1, int render2 + ){ + + // Handle the appearance and disappearances of the images + + // 0 = upwards, 1 = downwards || 0 = left, 1 = right + + // Handle the spell text + + int spelltext = ObjText_Create(); + ObjText_SetText(spelltext, spellname); + ObjText_SetFontType(spelltext, "Connecting Chain Handserif"); + + ObjText_SetFontSize(spelltext, textsize); + ObjText_SetFontColorTop(spelltext, 255, 255, 255); + ObjText_SetFontColorBottom(spelltext, 255, 255, 255); + ObjText_SetFontBorderType(spelltext, BORDER_FULL); + ObjText_SetFontBorderColor(spelltext, bordercolor); + ObjText_SetFontBorderWidth(spelltext, bordersize); + + ObjText_SetHorizontalAlignment(spelltext, ALIGNMENT_RIGHT); + ObjText_SetMaxWidth(spelltext, GetStgFrameWidth); + Obj_SetRenderPriorityI(spelltext, 79); + ObjRender_SetPosition(spelltext, textstartx, GetStgFrameHeight/8-10, 0); // WIP + ObjRender_SetAlpha(spelltext, 255); + + // Handle the spell bonus + + let objBonus = ObjText_Create(); + ObjText_SetFontSize(objBonus, 38); + ObjText_SetFontBold(objBonus, true); + ObjText_SetFontType(objBonus, "Anke Calligraph"); + ObjText_SetFontColorTop(objBonus, 255, 255, 255); + ObjText_SetFontColorBottom(objBonus, 255, 255, 255); + ObjText_SetFontBorderType(objBonus, BORDER_FULL); + ObjText_SetFontBorderColor(objBonus, bonusbordercolor); + ObjText_SetFontBorderWidth(objBonus, 2); + + ObjText_SetHorizontalAlignment(objBonus, ALIGNMENT_RIGHT); + ObjText_SetMaxWidth(objBonus, GetStgFrameWidth-24); + Obj_SetRenderPriorityI(objBonus, 79); + ObjRender_SetPosition(objBonus, textendx, GetStgFrameHeight/8+12, 0); // WIP + ObjRender_SetAlpha(objBonus, 255); + + async{ + while(ObjEnemyBossScene_GetInfo(spellID, INFO_PLAYER_SHOOTDOWN_COUNT) == 0 && ObjEnemyBossScene_GetInfo(spellID, INFO_PLAYER_SPELL_COUNT) == 0) + { + int score = trunc(ObjEnemyBossScene_GetInfo(spellID, INFO_SPELL_SCORE)/10) * 10; + score = min(score, 9999999990); + let yass = DigitToCommaArray(score); + ObjText_SetText(objBonus, yass); + yield; + } + ObjText_SetText(objBonus, ":("); + } + + // Actually call the tasks and functions here + + // Mm + + int objCutin1 = _Create2DImage(image1, rectleft, recttop, rectright, rectbottom); + int objCutin2 = _Create2DImage(image2, rectleft, recttop, rectright, rectbottom); + + Obj_SetRenderPriorityI(objCutin1, render1); + Obj_SetRenderPriorityI(objCutin2, render2); + + _MoveVertical(objCutin1, 0, 0); + _MoveVertical(objCutin2, 1, 1); + + //WriteLog(ObjRender_GetY(objCutin1)); + + //_MoveIntoPlace(spelltext, textstartx, textendx); + _FadeAtPlayer(spelltext); + _FadeAtPlayer(objBonus); + + while(ObjEnemyBossScene_GetInfo(spellID, INFO_CURRENT_LIFE) > 0){yield;} + + Obj_Delete(spelltext); + Obj_Delete(objBonus); + + //return; + +} + +task _SoloCutin( + image, + int rectleft, int recttop, int rectright, int rectbottom, + int bossID, int spellID, string spellname, + float textsize, float bordersize, int bordercolor, int bonusbordercolor, + float textstartx, float texty, int render + ){ + + // Handle the spell text + + int spelltext = ObjText_Create(); + ObjText_SetText(spelltext, spellname); + ObjText_SetFontType(spelltext, "Connecting Chain Handserif"); + + ObjText_SetFontSize(spelltext, textsize); + ObjText_SetFontColorTop(spelltext, 255, 255, 255); + ObjText_SetFontColorBottom(spelltext, 255, 255, 255); + ObjText_SetFontBorderType(spelltext, BORDER_FULL); + ObjText_SetFontBorderColor(spelltext, bordercolor); + ObjText_SetFontBorderWidth(spelltext, bordersize); + + ObjText_SetHorizontalAlignment(spelltext, ALIGNMENT_LEFT); + //ObjText_SetMaxWidth(spelltext, GetStgFrameWidth); + Obj_SetRenderPriorityI(spelltext, 79); + ObjRender_SetPosition(spelltext, textstartx, texty, 0); // WIP + ObjRender_SetAlpha(spelltext, 255); + + // Handle the spell bonus + + let objBonus = ObjText_Create(); + ObjText_SetFontSize(objBonus, textsize*1.25); + ObjText_SetFontBold(objBonus, true); + ObjText_SetFontType(objBonus, "Anke Calligraph"); + ObjText_SetFontColorTop(objBonus, 255, 255, 255); + ObjText_SetFontColorBottom(objBonus, 255, 255, 255); + ObjText_SetFontBorderType(objBonus, BORDER_FULL); + ObjText_SetFontBorderColor(objBonus, bonusbordercolor); + ObjText_SetFontBorderWidth(objBonus, 2); + + ObjText_SetHorizontalAlignment(objBonus, ALIGNMENT_LEFT); + //ObjText_SetMaxWidth(objBonus, GetStgFrameWidth-24); + Obj_SetRenderPriorityI(objBonus, 79); + ObjRender_SetPosition(objBonus, textstartx, texty+textsize-5, 0); // WIP + ObjRender_SetAlpha(objBonus, 255); + + async{ + while(ObjEnemyBossScene_GetInfo(spellID, INFO_PLAYER_SHOOTDOWN_COUNT) == 0 && ObjEnemyBossScene_GetInfo(spellID, INFO_PLAYER_SPELL_COUNT) == 0) + { + int score = trunc(ObjEnemyBossScene_GetInfo(spellID, INFO_SPELL_SCORE)/10) * 10; + score = min(score, 9999999990); + let yass = DigitToCommaArray(score); + ObjText_SetText(objBonus, "Bonus: " ~ yass); + yield; + } + ObjText_SetText(objBonus, "Bonus Failed..."); + } + + // Actually call the tasks and functions here + + // Mm + + int objCutin = _Create2DImage(image, rectleft, recttop, rectright, rectbottom); + + Obj_SetRenderPriorityI(objCutin, render); + + _MoveDiagonal(objCutin, GetStgFrameWidth()*1.25, -120, GetStgFrameWidth()/2, GetStgFrameHeight()/2, -120, GetStgFrameHeight()*1.25); + //WriteLog(Obj_IsVisible(spelltext)); + + //_MoveIntoPlace(spelltext, textstartx, textendx); + _FadeAtPlayer(spelltext); + _FadeAtPlayer(objBonus); + + while(ObjEnemyBossScene_GetInfo(spellID, INFO_CURRENT_LIFE) > 0){yield;} + + Obj_Delete(spelltext); + Obj_Delete(objBonus); + + //return; + +} + +// Tasks meant to be used with cutin tasks. + +task _MoveVertical(int target, int move, int widthposition){ + + float positionstart = [GetStgFrameHeight()*1.5, -GetStgFrameHeight()][move]; + float positionmid = GetStgFrameHeight()/2; + float positionend = [-GetStgFrameHeight()*1.5, GetStgFrameHeight()*1.5][move]; + + float positionhort = [3*GetStgFrameWidth/8, 6*GetStgFrameWidth/8][widthposition]; + + ObjRender_SetPosition(target, positionhort, positionstart, 0); + + ascent(i in 0..30){ + ObjRender_SetY(target, Interpolate_Decelerate(positionstart, positionmid, i/30)); + yield; + } + + wait(30); + + ascent(i in 0..30){ + ObjRender_SetY(target, Interpolate_Accelerate(positionmid, positionend, i/30)); + yield; + } + + Obj_Delete(target); + + return; + +} + +task _MoveDiagonal(int target, int startx, int starty, int midx, int midy, int endx, int endy){ + + //" + + ObjRender_SetPosition(target, startx, endx, 1); + + ascent(i in 0..30){ + ObjRender_SetPosition(target, Interpolate_Decelerate(startx, midx, i/30), Interpolate_Decelerate(starty, midy, i/30), 1); + ObjRender_SetAlpha(target, Interpolate_Decelerate(0, 255, i/30)); + yield; + } + + wait(30); + + ascent(i in 0..30){ + ObjRender_SetPosition(target, Interpolate_Decelerate(midx, endx, i/30), Interpolate_Decelerate(midy, endy, i/30), 1); + ObjRender_SetAlpha(target, Interpolate_Decelerate(255, 0, i/30)); + yield; + } + + return; + +} + +task _MoveIntoPlace(int target, int startx, int endx){ + ascent(i in 0..30){ + ObjRender_SetX(target, Interpolate_Decelerate(startx, endx, i/30)); + ObjRender_SetAlpha(target, Interpolate_Decelerate(0, 255, i/30)); + yield; + } + return; +} + +task _FadeAtPlayer(int target){ + wait(30); + while(!Obj_IsDeleted(target)){ + int player = GetPlayerObjectID(); + if(ObjRender_GetY(player) <= GetStgFrameHeight()/3.5){ObjRender_SetAlpha(target, 60);} + else{ObjRender_SetAlpha(target, 255);} + yield; + } + return; +} + +// Enemy render tasks + +/* +These render tasks assume the order of the spritesheet goes like this: + +Idle Idle2 Idle3 ... +Left Left2 Left3 ... +Right + +*/ + +task _RenderEnemyMovement(int obj, int frame, int offsetleft, int offsettop, int width, int height, float flipscale, int frameno, int speed){ + + ObjSprite2D_SetSourceRect(obj, offsetleft+width*floor(frame/speed), offsettop, width+width*floor(frame/speed), offsettop+height); + ObjRender_SetScaleX(obj, flipscale); + +} + +task _EnemyRenderFull(int enemyobj, int texture, int offsetleft, int offsettop, int width, int height, int framenoidle, int framenomovement, int speed){ + + int aniidle = 0; + int animove = 0; + + while(!Obj_IsDeleted(enemyobj)){ + + float dir = ObjMove_GetAngle(enemyobj); + float speed = ObjMove_GetSpeed(enemyobj); + + // Idle + if (speed == 0){ + _RenderEnemyMovement(enemyobj, aniidle, offsetleft, offsettop, width, height, 1, framenoidle, speed); + aniidle++; + if(aniidle >= speed*framenoidle){aniidle = 0;} + } + // Left + else if (cos(dir) < 0){ + _RenderEnemyMovement(enemyobj, aniidle, offsetleft, offsettop+height, width, height*2, 1, framenomovement, speed); + animove++; + if(animove >= speed*framenomovement){animove = 0;} + } + // Right + else if (cos(dir) > 0){ + _RenderEnemyMovement(enemyobj, aniidle, offsetleft, offsettop+height*2, width, height*3, 1, framenomovement, speed); + animove++; + if(animove >= speed*framenomovement){animove = 0;} + } + yield; + } +} + +// Drop a number of point items and petals depending on how fast you kill the enemy and how close you are to them. + +task _EnemyItemDrop( + int ID, bool isFlying, + int minPoint, int minPIV, + int maxPoint, int maxPIV, + int maxTimer, int maxDist + ){ + + //wait(spawnTime+5); + float enmX = ObjMove_GetX(ID), enmY = ObjMove_GetY(ID); + int Bitch = ID; + float timer = 1; + float dmgCheck = 0; + + ObjEnemy_SetDamageRate(Bitch, 100, 100); + + while(ObjEnemy_GetInfo(Bitch, INFO_LIFE) > 0){ + + enmX = ObjMove_GetX(Bitch); + enmY = ObjMove_GetY(Bitch); + timer++; + yield; + + } + + if( + (-128 < enmX && enmX < STG_WIDTH+128) + && + (-128 < enmY && enmY < STG_HEIGHT+128) + ) + + { + + if (isFlying) {SetCommonDataPtr(FLYINGENM_PTR, GetCommonDataPtr(FLYINGENM_PTR, 0)+1);} + else {SetCommonDataPtr(GROUNDENM_PTR, GetCommonDataPtr(GROUNDENM_PTR, 0)+1);} + + //_ExplosionEffect(enmX, enmY, PetalEffect); + //_ScorePopup(float enmX, float enmY, int pointNum, int pivNum); + + // NotifyEvent is faster than NotifyEventAll, considering how the item event will be called many times. + + NotifyEvent(GetCommonDataPtr(ITEMID_PTR, 0), EV_DROP_POINT_ENEMY, [enmX, enmY], timer, maxTimer, minPoint, maxPoint); + //NotifyEvent(GetCommonDataPtr(ITEMID_PTR, 0), EV_DROP_PIV_ENEMY, GetPlayerObjectID(), [enmX, enmY], minPIV, maxPIV, maxDist); + NotifyEvent(GetCommonDataPtr(SYSTEMID_PTR, 0), EV_EXPLODE, [enmX, enmY]); + + } + + else{} + +} + +// Overload with special weapon ammo + +task _EnemyItemDrop( + int ID, bool isFlying, + float minPoint, float minPIV, float minAmmo, + float maxPoint, float maxPIV, float maxAmmo, + float maxTimer, float maxDist + ){ + + //wait(spawnTime+5); + float enmX = ObjMove_GetX(ID), enmY = ObjMove_GetY(ID); + int Bitch = ID; + float timer = 1; + float dmgCheck = 0; + + ObjEnemy_SetDamageRate(Bitch, 100, 100); + + while(ObjEnemy_GetInfo(Bitch, INFO_LIFE) > 0){ + + enmX = ObjMove_GetX(Bitch); + enmY = ObjMove_GetY(Bitch); + timer++; + yield; + + } + + if( + (-128 < enmX && enmX < STG_WIDTH+128) + && + (-128 < enmY && enmY < STG_HEIGHT+128) + ) + + { + + if (isFlying) {SetCommonDataPtr(FLYINGENM_PTR, GetCommonDataPtr(FLYINGENM_PTR, 0)+1);} + else {SetCommonDataPtr(GROUNDENM_PTR, GetCommonDataPtr(GROUNDENM_PTR, 0)+1);} + + //_ExplosionEffect(enmX, enmY, PetalEffect); + //_ScorePopup(float enmX, float enmY, int pointNum, int pivNum); + + // NotifyEvent is faster than NotifyEventAll, considering how the item event will be called many times. + + NotifyEvent(GetCommonDataPtr(ITEMID_PTR, 0), EV_DROP_POINT_ENEMY, [enmX, enmY], timer, maxTimer, minPoint, maxPoint); + + // Comment these out for NarumiSTG + + //NotifyEvent(GetCommonDataPtr(ITEMID_PTR, 0), EV_DROP_PIV_ENEMY, GetPlayerObjectID(), [enmX, enmY], minPIV, maxPIV, maxDist); + //NotifyEvent(GetCommonDataPtr(ITEMID_PTR, 0), EV_DROP_AMMO_ENEMY, GetPlayerObjectID(), [enmX, enmY], minAmmo, maxAmmo, maxDist); + NotifyEvent(GetCommonDataPtr(SYSTEMID_PTR, 0), EV_EXPLODE, [enmX, enmY]); + + } + + else{} + +} \ No newline at end of file diff --git a/script/KevinSystem/Universal_Lib.txt b/script/KevinSystem/Universal_Lib.txt new file mode 100644 index 0000000..6dcfe8d --- /dev/null +++ b/script/KevinSystem/Universal_Lib.txt @@ -0,0 +1,440 @@ +/* -------------------------------------------------------------------- + + /////////////// UNIVERSAL/GENERAL LIBRARY ///////////////// + + A library meant for universal functions and including other libraries. + + -------------------------------------------------------------------- +*/ + +let blipVol = 3 * GetAreaCommonData("Config", "SEVol", 100) * 0.01; + +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" + +#include "script/KevinSystem/kevin_system/Kevin_ItemLib.txt" +#include "script/KevinSystem/kevin_system/Kevin_ItemConst.txt" +#include "script/default_system/Default_Effect.txt" // Probably change this somewhere down the line. + +#include "script/KevinSystem/GeneralSoundLib.txt" // Ryannlib momento +#include "script/KevinSystem/TerraShot2x/shot_const.dnh" + +#include "script/KevinSystem/Universal_EnemyLib.dnh" + +#include "script/KevinSystem/KevinShot/shotconst_HD.txt" + +// Convenience constants + +// Placeholder + +let invalid = "script/KevinSystem/img/lol.png"; + +LoadTextureEx(invalid, true, true); + +let sound = ObjSound_Create(); +ObjSound_Load(sound, "script/game/resourceLib/dialogueblip.wav"); +ObjSound_SetVolumeRate(sound, 100 * blipVol); +ObjSound_SetSoundDivision(sound, SOUND_SE); + +// Shortened version of very commonly used functions + +function FUNC_LERP_DECEL(a, b, x){ + float res = Interpolate_Decelerate(a, b, x); + return res; +} + +function FUNC_LERP_ACCEL(a, b, x){ + float res = Interpolate_Accelerate(a, b, x); + return res; +} + +function FUNC_LERP_LINEAR(a, b, x){ + float res = Interpolate_Linear(a, b, x); + return res; +} + +function FUNC_LERP_SMOOTH(a, b, x){ + float res = Interpolate_Smooth(a, b, x); + return res; +} + +function FUNC_LERP_SMOOTHER(a, b, x){ + float res = Interpolate_Smoother(a, b, x); + return res; +} + +//_EffectListPreRender(PetalEffect, testEnemyTex, [1536, 0, 1792, 256]); +_SoundTask; + +function DigitToCommaArray(num){ //Natashinitai + + let srcStr = IntToString(num); + let res = []; + let nChar = 0; + for(let i = length(srcStr) - 1; i >= 0; i--){ + res = [srcStr[i]] ~ res; + nChar++; + if(nChar % 3 == 0 && i > 0) res = "," ~ res; + } + return res; + +} + +// thanks mugenri uwu + +function TTextScroll(int obj_, string text_) { //Makes text fill gradually in text boxes + + bool dialogEnd = false; + bool sentenceEnd = false; + string[] tempStrings = SplitString(text_, "/"); //use / for newlines instead of [r] + string tempString = ""; + char lastChar; + int waitTime; + + async{ + while(!dialogEnd){ + if(sentenceEnd){wait(4); continue;} + else{ObjSound_Play(sound); wait(4);} + } + } + + if (GetVirtualKeyState(VK_OK) == KEY_PUSH) { //Prevents skipping the yield + SetVirtualKeyState(VK_OK, KEY_FREE); + } + + ascent (i in 0..length(tempStrings)) { //list of substrings + ascent (j in 0..length(tempStrings[i])) { //for each character in a substring + tempString ~= [tempStrings[i][j]]; + lastChar = tempString[-1]; + ObjText_SetText(obj_, tempString); + if([tempStrings[i][j]] == "." || + [tempStrings[i][j]] == "," || + [tempStrings[i][j]] == "!" ) {sentenceEnd = true; wait(10);} + else {wait(2); sentenceEnd = false;} + } + tempString ~= ['[','r',']']; //append a newline after each substring + } + + dialogEnd = true; + wait(30); + +} + +// Simple text object creation (adapted from mkm) + +function CreateTextObject( + float mx, my, size, + string text, font, + int colorTop, colorBottom, + int borderColor, borderWidth, + int renderPriority + ){ + + let obj = ObjText_Create(); + ObjText_SetText(obj, text); + ObjText_SetFontSize(obj, size); + ObjText_SetFontType(obj, font); + ObjText_SetFontColorTop(obj, colorTop); + ObjText_SetFontColorBottom(obj, colorBottom); + ObjText_SetFontBorderType(obj, BORDER_FULL); + ObjText_SetFontBorderColor(obj, borderColor); + ObjText_SetFontBorderWidth(obj, borderWidth); + Obj_SetRenderPriorityI(obj, renderPriority); + ObjRender_SetX(obj, mx); + ObjRender_SetY(obj, my); + return obj; + +} + +// Simple 2D image creation + +function _Create2DImage(imgpath, int rectleft, int recttop, int rectright, int rectbottom){ + + int imgname = ObjPrim_Create(OBJ_SPRITE_2D); + ObjPrim_SetTexture(imgname, imgpath); + ObjSprite2D_SetSourceRect(imgname, rectleft, recttop, rectright, rectbottom); + ObjSprite2D_SetDestCenter(imgname); + //ObjRender_SetPosition(imgname, positionstart) + + return imgname; +} + +// Overload that uses arrays instead + +function _Create2DImage(imgpath, int[] rectarray){ + + int imgname = ObjPrim_Create(OBJ_SPRITE_2D); + ObjPrim_SetTexture(imgname, imgpath); + ObjSprite2D_SetSourceRect(imgname, rectarray); + ObjSprite2D_SetDestCenter(imgname); + //ObjRender_SetPosition(imgname, positionstart) + + return imgname; +} + +// Overload with texture load option + +function _Create2DImage(imgpath, int[] rectarray, bool loadEx){ + + if(loadEx){LoadTextureEx(imgpath, true, true);} + + int imgname = ObjPrim_Create(OBJ_SPRITE_2D); + ObjPrim_SetTexture(imgname, imgpath); + ObjSprite2D_SetSourceRect(imgname, rectarray); + ObjSprite2D_SetDestCenter(imgname); + //ObjRender_SetPosition(imgname, positionstart) + + return imgname; + +} + + +// Task to make bullet fade after a certain time, bullet loses hitbox while fading + +task _EnemyShotFade(int target, int time, bool fadedelay, float delaymultiplier){ + ObjShot_SetDeleteFrame(target, time); + if (fadedelay){ + wait(time-time/delaymultiplier); + ObjShot_SetIntersectionEnable(target, false); + ascent(i in 0..time/delaymultiplier){ + ObjRender_SetAlpha(target, Interpolate_Smoother(ObjRender_GetAlpha(target), 0, i/(time/delaymultiplier))); + yield; + } + } + else{ + ascent(i in 0..time){ + ObjRender_SetAlpha(target, Interpolate_Smoother(ObjRender_GetAlpha(target), 0, i/time)); + yield; + } + } + return; +} + +// Delay function by Naudiz + +task _Delay(target, del){ + + ObjShot_SetDelay(target, del); + ObjShot_SetDelayGraphic(target, ObjShot_GetImageID(target)); // unless you already have the ID in the function somewhere, in which case you can just use that, or use any other graphic + ObjShot_SetDelayMode(target, DELAY_LERP, LERP_ACCELERATE, LERP_DECELERATE); // delay mode, scale lerp, alpha lerp (these are the modes I use in my entry) + ObjShot_SetDelayColoringEnable(target, true); + ObjShot_SetDelayScaleParameter(target, 1, 2, del); // lerps from 2 to 1 scale in del frames (use the value from ObjShot_SetDelay for del) + ObjShot_SetDelayAlphaParameter(target, 1, 0, del); // lerps from 0 to 1 (255) alpha in del frames + + return; +} + +// Overloads by me + +task _Delay(target, del, orgscale, destscale, orgalpha, destalpha, scalelerp, alphalerp){ + + ObjShot_SetDelay(target, del); + ObjShot_SetDelayGraphic(target, ObjShot_GetImageID(target)); + ObjShot_SetDelayColoringEnable(target, true); + ObjShot_SetDelayMode(target, DELAY_LERP, scalelerp, alphalerp); + ObjShot_SetDelayScaleParameter(target, destscale, orgscale, del); + ObjShot_SetDelayAlphaParameter(target, destalpha, orgalpha, del); + return; + +} + +task _Delay(target, del, orgscale, destscale, orgalpha, destalpha){ + + ObjShot_SetDelay(target, del); + ObjShot_SetDelayGraphic(target, ObjShot_GetImageID(target)); + ObjShot_SetDelayColoringEnable(target, true); + ObjShot_SetDelayMode(target, DELAY_LERP, LERP_ACCELERATE, LERP_DECELERATE); + ObjShot_SetDelayScaleParameter(target, destscale, orgscale, del); + ObjShot_SetDelayAlphaParameter(target, destalpha, orgalpha, del); + return; + +} + +task _Delay(target, del, orgscale, orgalpha){ + + ObjShot_SetDelay(target, del); + ObjShot_SetDelayGraphic(target, ObjShot_GetImageID(target)); + ObjShot_SetDelayColoringEnable(target, true); + ObjShot_SetDelayMode(target, DELAY_LERP, LERP_ACCELERATE, LERP_DECELERATE); + ObjShot_SetDelayScaleParameter(target, 1, orgscale, del); + ObjShot_SetDelayAlphaParameter(target, 1, orgalpha, del); + return; + +} + +// Rescales the bullet. Very important. + +task _BulletRescale(target, float scale, bool hitboxscale, hitboxlevel){ + + ObjRender_SetScaleXYZ(target, scale, scale, 1); + + if (hitboxscale){ + ObjShot_SetIntersectionScaleXY(target, scale*hitboxlevel, scale*hitboxlevel); + return; + } + + else{return;} + +} + +// Item drop functions. + +//////////// TO-DO: Move all item creation to the item script, rendering both of these tasks obsolete. //////////// + +task _NonspellItemDrop(int targetscene, int targetenemy, int itemamount){ + + float ex = ObjMove_GetX(targetenemy); + float ey = ObjMove_GetY(targetenemy); + + if(ObjEnemyBossScene_GetInfo(targetscene, INFO_PLAYER_SHOOTDOWN_COUNT) == 0){ + loop(itemamount){ + CreateScoreItem(POINT_REGULAR, rand(ex-90, ex+90), rand(ey-90, ey+90)); + } + } + else{ + loop(trunc(itemamount/2)){ + CreateScoreItem(POINT_REGULAR, rand(ex-90, ex+90), rand(ey-90, ey+90)); + } + } + +} + +task _SpellItemDrop(int targetscene, int targetenemy, int itemamount){ + + float ex = ObjMove_GetX(targetenemy); + float ey = ObjMove_GetY(targetenemy); + + if(ObjEnemyBossScene_GetInfo(targetscene, INFO_PLAYER_SHOOTDOWN_COUNT) == 0 && ObjEnemyBossScene_GetInfo(targetscene, INFO_PLAYER_SPELL_COUNT) == 0){ + loop(itemamount){ + CreateScoreItem(POINT_BHESTIE, rand(ex-90, ex+90), rand(ey-90, ey+90)); + } + } + else if (ObjEnemyBossScene_GetInfo(targetscene, INFO_PLAYER_SHOOTDOWN_COUNT) == 0 && ObjEnemyBossScene_GetInfo(targetscene, INFO_PLAYER_SPELL_COUNT) >= 0){ + loop(trunc(itemamount/2)){ + CreateScoreItem(POINT_BHESTIE, rand(ex-90, ex+90), rand(ey-90, ey+90)); + } + } + else{} + +} + +// By Neck_Logo + +task _CreateCustomTelegraphLine( + float posX_, float posY_, + float initAngle_, float destAngle_, + float initLength_, float destLength_, + float initWidth_, float destWidth_, + int color_, int maxAlpha_, + float growthTime_, float lifeTime_, float fadeTime_ + ) // damn this is some cursed indenting + { + int scene = GetEnemyBossSceneObjectID(); + + let _shotF_Telegraph_Line = ObjParticleList_Create(OBJ_PARTICLE_LIST_2D); + ObjPrim_SetTexture(_shotF_Telegraph_Line, invalid); + + Obj_SetRenderPriorityI(_shotF_Telegraph_Line, 37); + ObjPrim_SetPrimitiveType(_shotF_Telegraph_Line, PRIMITIVE_TRIANGLELIST); + ObjPrim_SetVertexCount(_shotF_Telegraph_Line, 4); + + ObjRender_SetBlendType(_shotF_Telegraph_Line, BLEND_ALPHA); + + // + + float dU = 0.5, dV = 0.5; + // Left-top, right-top, left-bottom, right-bottom + + ObjPrim_SetVertexUVT(_shotF_Telegraph_Line, 0, 0, 0); + ObjPrim_SetVertexUVT(_shotF_Telegraph_Line, 1, 1, 0); + ObjPrim_SetVertexUVT(_shotF_Telegraph_Line, 2, 0, 1); + ObjPrim_SetVertexUVT(_shotF_Telegraph_Line, 3, 1, 1); + + // Vertex positions are offset with deltas so that the sprite is centered + + ObjPrim_SetVertexPosition(_shotF_Telegraph_Line, 0, -dU, -dV, 1); + ObjPrim_SetVertexPosition(_shotF_Telegraph_Line, 1, dU, -dV, 1); + ObjPrim_SetVertexPosition(_shotF_Telegraph_Line, 2, -dU, dV, 1); + ObjPrim_SetVertexPosition(_shotF_Telegraph_Line, 3, dU, dV, 1); + + ObjPrim_SetVertexIndex(_shotF_Telegraph_Line, [0, 1, 2, 1, 2, 3]); + + float angle = initAngle_; + float span = initLength_; + float width = initWidth_; + int alpha = 0; + + //_CreateParticleList(); + _TelegraphLineControl(); + + if(scene != ID_INVALID){ + // growth phase + for (int i = 1; i <= growthTime_ && 0 < ObjEnemyBossScene_GetInfo(scene, INFO_ACTIVE_STEP_TOTAL_LIFE); i++) { + width = Interpolate_Decelerate(initWidth_, destWidth_, i / growthTime_); + alpha = Interpolate_Decelerate(0, maxAlpha_+32, i / growthTime_); + RenderTelegraphLine(); + yield; + } + + // static phase + for (int j = 1; j <= lifeTime_ && 0 < ObjEnemyBossScene_GetInfo(scene, INFO_ACTIVE_STEP_TOTAL_LIFE); j++) { + RenderTelegraphLine(); + yield; + } + + if (!(0 < ObjEnemyBossScene_GetInfo(scene, INFO_ACTIVE_STEP_TOTAL_LIFE))) fadeTime_ = min(fadeTime_, 25); + + } + + else{ + for (int i = 1; i <= growthTime_ ; i++) { + width = Interpolate_Decelerate(initWidth_, destWidth_, i / growthTime_); + alpha = Interpolate_Decelerate(0, maxAlpha_+32, i / growthTime_); + RenderTelegraphLine(); + yield; + } + + // static phase + for (int j = 1; j <= lifeTime_; j++) { + RenderTelegraphLine(); + yield; + } + + } + + destWidth_ = width; + maxAlpha_ = alpha; + + // deletion phase + for (int k = 1; k <= fadeTime_; k++) { + width = Interpolate_Accelerate(destWidth_, destWidth_ - (destWidth_ - initWidth_) / 2, k / fadeTime_); + alpha = Interpolate_Accelerate(maxAlpha_+32, 0, k / fadeTime_); + RenderTelegraphLine(); + yield; + } + + Obj_Delete(_shotF_Telegraph_Line); + + task _TelegraphLineControl() { + for (int l = 1; l <= growthTime_ + lifeTime_; l++) { + angle = Interpolate_Decelerate(initAngle_, destAngle_, l / (growthTime_ + lifeTime_)); + span = Interpolate_Decelerate(initLength_, destLength_, l / (growthTime_ + lifeTime_)); + yield; + } + } + + function RenderTelegraphLine() { + + float midX = posX_ + span * cos(angle) + (width / 2) * cos(angle + 90); + float midY = posY_ + span * sin(angle) + (width / 2) * sin(angle + 90); + + ObjParticleList_SetPosition(_shotF_Telegraph_Line, midX, midY, 1); + ObjParticleList_SetScale(_shotF_Telegraph_Line, span, width, 1); + ObjParticleList_SetAngleZ(_shotF_Telegraph_Line, angle); + ObjParticleList_SetColor(_shotF_Telegraph_Line, color_); + ObjParticleList_SetAlpha(_shotF_Telegraph_Line, alpha); + ObjParticleList_AddInstance(_shotF_Telegraph_Line); + + } + + //return _shotF_Telegraph_Line; +} diff --git a/script/KevinSystem/font/AnkeCall.ttf b/script/KevinSystem/font/AnkeCall.ttf new file mode 100644 index 0000000..0750e2c Binary files /dev/null and b/script/KevinSystem/font/AnkeCall.ttf differ diff --git a/script/KevinSystem/font/Connecting Chain Handserif.ttf b/script/KevinSystem/font/Connecting Chain Handserif.ttf new file mode 100644 index 0000000..5da2352 Binary files /dev/null and b/script/KevinSystem/font/Connecting Chain Handserif.ttf differ diff --git a/script/KevinSystem/font/Corporate-Logo-Rounded.otf b/script/KevinSystem/font/Corporate-Logo-Rounded.otf new file mode 100644 index 0000000..4297b86 Binary files /dev/null and b/script/KevinSystem/font/Corporate-Logo-Rounded.otf differ diff --git a/script/KevinSystem/font/Exotic 350 Demi Bold BT.ttf b/script/KevinSystem/font/Exotic 350 Demi Bold BT.ttf new file mode 100644 index 0000000..a52b433 Binary files /dev/null and b/script/KevinSystem/font/Exotic 350 Demi Bold BT.ttf differ diff --git a/script/KevinSystem/font/FOT-NewCinemaAStd-D_1.otf b/script/KevinSystem/font/FOT-NewCinemaAStd-D_1.otf new file mode 100644 index 0000000..32665c5 Binary files /dev/null and b/script/KevinSystem/font/FOT-NewCinemaAStd-D_1.otf differ diff --git a/script/KevinSystem/font/GravityBold8.ttf b/script/KevinSystem/font/GravityBold8.ttf new file mode 100644 index 0000000..5e119db Binary files /dev/null and b/script/KevinSystem/font/GravityBold8.ttf differ diff --git a/script/KevinSystem/font/GravityRegular5.ttf b/script/KevinSystem/font/GravityRegular5.ttf new file mode 100644 index 0000000..8107b31 Binary files /dev/null and b/script/KevinSystem/font/GravityRegular5.ttf differ diff --git a/script/KevinSystem/font/OtsutomeFont_Ver3.ttf b/script/KevinSystem/font/OtsutomeFont_Ver3.ttf new file mode 100644 index 0000000..63f8be7 Binary files /dev/null and b/script/KevinSystem/font/OtsutomeFont_Ver3.ttf differ diff --git a/script/KevinSystem/font/Revue Regular.ttf b/script/KevinSystem/font/Revue Regular.ttf new file mode 100644 index 0000000..493921f Binary files /dev/null and b/script/KevinSystem/font/Revue Regular.ttf differ diff --git a/script/KevinSystem/font/Uni Sans Heavy.otf b/script/KevinSystem/font/Uni Sans Heavy.otf new file mode 100644 index 0000000..facd333 Binary files /dev/null and b/script/KevinSystem/font/Uni Sans Heavy.otf differ diff --git a/script/KevinSystem/font/YasashisaGothicBold-V2.otf b/script/KevinSystem/font/YasashisaGothicBold-V2.otf new file mode 100644 index 0000000..41b475b Binary files /dev/null and b/script/KevinSystem/font/YasashisaGothicBold-V2.otf differ diff --git a/script/KevinSystem/font/origa___.ttf b/script/KevinSystem/font/origa___.ttf new file mode 100644 index 0000000..61615f2 Binary files /dev/null and b/script/KevinSystem/font/origa___.ttf differ diff --git a/script/KevinSystem/font/unispace rg.ttf b/script/KevinSystem/font/unispace rg.ttf new file mode 100644 index 0000000..66284c3 Binary files /dev/null and b/script/KevinSystem/font/unispace rg.ttf differ diff --git a/script/KevinSystem/img/Default_Background_IceMountain.bmp b/script/KevinSystem/img/Default_Background_IceMountain.bmp new file mode 100644 index 0000000..61db0b6 Binary files /dev/null and b/script/KevinSystem/img/Default_Background_IceMountain.bmp differ diff --git a/script/KevinSystem/img/Default_Background_IceMountain.mqo b/script/KevinSystem/img/Default_Background_IceMountain.mqo new file mode 100644 index 0000000..f2388aa --- /dev/null +++ b/script/KevinSystem/img/Default_Background_IceMountain.mqo @@ -0,0 +1,249 @@ +Metasequoia Document +Format Text Ver 1.0 + +Scene { + pos -30.1096 -34.3943 789.2167 + lookat 0.0000 0.0000 0.0000 + head -1.8300 + pich 0.5300 + ortho 0 + zoom2 2.0091 + amb 0.250 0.250 0.250 +} +Material 1 { + "mat0" shader(3) col(1.000 1.000 1.000 1.000) dif(1.000) amb(0.600) emi(0.000) spc(0.000) power(1.00) tex("Default_Background_IceMountain.bmp") +} +Object "obj0" { + visible 15 + locking 0 + shading 1 + facet 59.5 + color 0.898 0.498 0.698 + color_type 0 + vertex 121 { + 500.0000 0.0000 500.0000 + 400.0000 0.0000 500.0000 + 400.0000 0.0000 400.0000 + 500.0000 0.0000 400.0000 + 300.0000 0.0000 500.0000 + 300.0000 0.0000 400.0000 + 200.0000 0.0000 500.0000 + 200.0000 0.0000 400.0000 + 100.0000 0.0000 500.0000 + 100.0000 0.0000 400.0000 + 0.0000 0.0000 500.0000 + 0.0000 0.0000 400.0000 + -100.0000 0.0000 500.0000 + -100.0000 0.0000 400.0000 + -200.0000 0.0000 500.0000 + -200.0000 0.0000 400.0000 + -300.0000 0.0000 500.0000 + -300.0000 0.0000 400.0000 + -400.0000 0.0000 500.0000 + -400.0000 0.0000 400.0000 + -500.0000 0.0000 500.0000 + -500.0000 0.0000 400.0000 + 400.0000 0.0000 300.0000 + 500.0000 0.0000 300.0000 + 300.0000 0.0000 300.0000 + 181.9993 25.4220 251.4612 + 87.5351 67.6823 172.7408 + 44.9009 66.8717 169.9153 + -84.3673 81.3440 243.9148 + -165.8140 45.4173 301.9575 + -265.8140 45.4173 301.9575 + -400.0000 0.0000 300.0000 + -500.0000 0.0000 300.0000 + 400.0000 0.0000 200.0000 + 500.0000 0.0000 200.0000 + 298.8597 14.8172 185.7207 + 126.2485 97.3682 134.2916 + 23.1660 119.7628 65.2812 + -48.3018 103.9974 84.5904 + -78.9084 75.3832 146.5701 + -165.8140 45.4173 201.9575 + -265.8140 45.4173 201.9575 + -400.0000 0.0000 200.0000 + -500.0000 0.0000 200.0000 + 400.0000 0.0000 100.0000 + 500.0000 0.0000 100.0000 + 255.6389 58.0200 114.1542 + 142.7559 56.0312 43.6297 + 36.2995 41.0596 -5.4791 + -62.4664 75.8076 -4.6157 + -140.5926 75.4124 49.9508 + -231.5631 8.7596 76.5071 + -300.0000 0.0000 100.0000 + -400.0000 0.0000 100.0000 + -500.0000 0.0000 100.0000 + 400.0000 0.0000 0.0000 + 500.0000 0.0000 0.0000 + 221.8938 66.4581 1.9473 + 143.8961 41.2140 -42.0910 + 15.1947 34.4286 -102.5772 + -71.9221 36.4174 -32.0527 + -158.7284 63.2710 -47.6829 + -211.9965 33.8983 -68.7922 + -280.4333 25.1387 -45.2993 + -400.0000 0.0000 0.0000 + -500.0000 0.0000 0.0000 + 400.0000 0.0000 -100.0000 + 500.0000 0.0000 -100.0000 + 300.0000 0.0000 -100.0000 + 200.0000 0.0000 -100.0000 + 28.0779 36.4174 -132.0527 + -71.9221 36.4174 -132.0527 + -109.7092 10.8928 -120.7280 + -174.9080 20.0401 -134.2268 + -274.9080 20.0401 -134.2268 + -400.0000 0.0000 -100.0000 + -500.0000 0.0000 -100.0000 + 400.0000 0.0000 -200.0000 + 500.0000 0.0000 -200.0000 + 258.7267 31.4519 -195.8992 + 154.2999 93.4632 -171.4050 + 83.7472 49.4622 -230.7452 + -16.2528 49.4622 -230.7452 + -139.3118 37.0325 -183.7692 + -214.2198 57.0726 -217.9960 + -274.9080 20.0401 -234.2268 + -400.0000 0.0000 -200.0000 + -500.0000 0.0000 -200.0000 + 400.0000 0.0000 -300.0000 + 500.0000 0.0000 -300.0000 + 287.1706 10.4937 -295.7311 + 187.1706 10.4937 -295.7311 + 125.2088 40.5356 -370.5968 + 25.2089 40.5356 -370.5968 + -139.3118 37.0325 -283.7693 + -239.3118 37.0325 -283.7693 + -300.0000 0.0000 -300.0000 + -400.0000 0.0000 -300.0000 + -500.0000 0.0000 -300.0000 + 400.0000 0.0000 -400.0000 + 500.0000 0.0000 -400.0000 + 300.0000 0.0000 -400.0000 + 200.0000 0.0000 -400.0000 + 100.0000 0.0000 -400.0000 + 0.0000 0.0000 -400.0000 + -100.0000 0.0000 -400.0000 + -200.0000 0.0000 -400.0000 + -300.0000 0.0000 -400.0000 + -400.0000 0.0000 -400.0000 + -500.0000 0.0000 -400.0000 + 400.0000 0.0000 -500.0000 + 500.0000 0.0000 -500.0000 + 300.0000 0.0000 -500.0000 + 200.0000 0.0000 -500.0000 + 100.0000 0.0000 -500.0000 + 0.0000 0.0000 -500.0000 + -100.0000 0.0000 -500.0000 + -200.0000 0.0000 -500.0000 + -300.0000 0.0000 -500.0000 + -400.0000 0.0000 -500.0000 + -500.0000 0.0000 -500.0000 + } + face 100 { + 4 V(0 1 2 3) M(0) UV(0.00000 0.00000 0.10000 0.00000 0.10000 0.10000 0.00000 0.10000) + 4 V(1 4 5 2) M(0) UV(0.10000 0.00000 0.20000 0.00000 0.20000 0.10000 0.10000 0.10000) + 4 V(4 6 7 5) M(0) UV(0.20000 0.00000 0.30000 0.00000 0.30000 0.10000 0.20000 0.10000) + 4 V(6 8 9 7) M(0) UV(0.30000 0.00000 0.40000 0.00000 0.40000 0.10000 0.30000 0.10000) + 4 V(8 10 11 9) M(0) UV(0.40000 0.00000 0.50000 0.00000 0.50000 0.10000 0.40000 0.10000) + 4 V(10 12 13 11) M(0) UV(0.50000 0.00000 0.60000 0.00000 0.60000 0.10000 0.50000 0.10000) + 4 V(12 14 15 13) M(0) UV(0.60000 0.00000 0.70000 0.00000 0.70000 0.10000 0.60000 0.10000) + 4 V(14 16 17 15) M(0) UV(0.70000 0.00000 0.80000 0.00000 0.80000 0.10000 0.70000 0.10000) + 4 V(16 18 19 17) M(0) UV(0.80000 0.00000 0.90000 0.00000 0.90000 0.10000 0.80000 0.10000) + 4 V(18 20 21 19) M(0) UV(0.90000 0.00000 1.00000 0.00000 1.00000 0.10000 0.90000 0.10000) + 4 V(3 2 22 23) M(0) UV(0.00000 0.10000 0.10000 0.10000 0.10000 0.20000 0.00000 0.20000) + 4 V(2 5 24 22) M(0) UV(0.10000 0.10000 0.20000 0.10000 0.20000 0.20000 0.10000 0.20000) + 4 V(5 7 25 24) M(0) UV(0.20000 0.10000 0.30000 0.10000 0.30000 0.20000 0.20000 0.20000) + 4 V(7 9 26 25) M(0) UV(0.30000 0.10000 0.40000 0.10000 0.40000 0.20000 0.30000 0.20000) + 4 V(9 11 27 26) M(0) UV(0.40000 0.10000 0.50000 0.10000 0.50000 0.20000 0.40000 0.20000) + 4 V(11 13 28 27) M(0) UV(0.50000 0.10000 0.60000 0.10000 0.60000 0.20000 0.50000 0.20000) + 4 V(13 15 29 28) M(0) UV(0.60000 0.10000 0.70000 0.10000 0.70000 0.20000 0.60000 0.20000) + 4 V(15 17 30 29) M(0) UV(0.70000 0.10000 0.80000 0.10000 0.80000 0.20000 0.70000 0.20000) + 4 V(17 19 31 30) M(0) UV(0.80000 0.10000 0.90000 0.10000 0.90000 0.20000 0.80000 0.20000) + 4 V(19 21 32 31) M(0) UV(0.90000 0.10000 1.00000 0.10000 1.00000 0.20000 0.90000 0.20000) + 4 V(23 22 33 34) M(0) UV(0.00000 0.20000 0.10000 0.20000 0.10000 0.30000 0.00000 0.30000) + 4 V(22 24 35 33) M(0) UV(0.10000 0.20000 0.20000 0.20000 0.20000 0.30000 0.10000 0.30000) + 4 V(24 25 36 35) M(0) UV(0.20000 0.20000 0.30000 0.20000 0.30000 0.30000 0.20000 0.30000) + 4 V(25 26 37 36) M(0) UV(0.30000 0.20000 0.40000 0.20000 0.40000 0.30000 0.30000 0.30000) + 4 V(26 27 38 37) M(0) UV(0.40000 0.20000 0.50000 0.20000 0.50000 0.30000 0.40000 0.30000) + 4 V(27 28 39 38) M(0) UV(0.50000 0.20000 0.60000 0.20000 0.60000 0.30000 0.50000 0.30000) + 4 V(28 29 40 39) M(0) UV(0.60000 0.20000 0.70000 0.20000 0.70000 0.30000 0.60000 0.30000) + 4 V(29 30 41 40) M(0) UV(0.70000 0.20000 0.80000 0.20000 0.80000 0.30000 0.70000 0.30000) + 4 V(30 31 42 41) M(0) UV(0.80000 0.20000 0.90000 0.20000 0.90000 0.30000 0.80000 0.30000) + 4 V(31 32 43 42) M(0) UV(0.90000 0.20000 1.00000 0.20000 1.00000 0.30000 0.90000 0.30000) + 4 V(34 33 44 45) M(0) UV(0.00000 0.30000 0.10000 0.30000 0.10000 0.40000 0.00000 0.40000) + 4 V(33 35 46 44) M(0) UV(0.10000 0.30000 0.20000 0.30000 0.20000 0.40000 0.10000 0.40000) + 4 V(35 36 47 46) M(0) UV(0.20000 0.30000 0.30000 0.30000 0.30000 0.40000 0.20000 0.40000) + 4 V(36 37 48 47) M(0) UV(0.30000 0.30000 0.40000 0.30000 0.40000 0.40000 0.30000 0.40000) + 4 V(37 38 49 48) M(0) UV(0.40000 0.30000 0.50000 0.30000 0.50000 0.40000 0.40000 0.40000) + 4 V(38 39 50 49) M(0) UV(0.50000 0.30000 0.60000 0.30000 0.60000 0.40000 0.50000 0.40000) + 4 V(39 40 51 50) M(0) UV(0.60000 0.30000 0.70000 0.30000 0.70000 0.40000 0.60000 0.40000) + 4 V(40 41 52 51) M(0) UV(0.70000 0.30000 0.80000 0.30000 0.80000 0.40000 0.70000 0.40000) + 4 V(41 42 53 52) M(0) UV(0.80000 0.30000 0.90000 0.30000 0.90000 0.40000 0.80000 0.40000) + 4 V(42 43 54 53) M(0) UV(0.90000 0.30000 1.00000 0.30000 1.00000 0.40000 0.90000 0.40000) + 4 V(45 44 55 56) M(0) UV(0.00000 0.40000 0.10000 0.40000 0.10000 0.50000 0.00000 0.50000) + 4 V(44 46 57 55) M(0) UV(0.10000 0.40000 0.20000 0.40000 0.20000 0.50000 0.10000 0.50000) + 4 V(46 47 58 57) M(0) UV(0.20000 0.40000 0.30000 0.40000 0.30000 0.50000 0.20000 0.50000) + 4 V(47 48 59 58) M(0) UV(0.30000 0.40000 0.40000 0.40000 0.40000 0.50000 0.30000 0.50000) + 4 V(48 49 60 59) M(0) UV(0.40000 0.40000 0.50000 0.40000 0.50000 0.50000 0.40000 0.50000) + 4 V(49 50 61 60) M(0) UV(0.50000 0.40000 0.60000 0.40000 0.60000 0.50000 0.50000 0.50000) + 4 V(50 51 62 61) M(0) UV(0.60000 0.40000 0.70000 0.40000 0.70000 0.50000 0.60000 0.50000) + 4 V(51 52 63 62) M(0) UV(0.70000 0.40000 0.80000 0.40000 0.80000 0.50000 0.70000 0.50000) + 4 V(52 53 64 63) M(0) UV(0.80000 0.40000 0.90000 0.40000 0.90000 0.50000 0.80000 0.50000) + 4 V(53 54 65 64) M(0) UV(0.90000 0.40000 1.00000 0.40000 1.00000 0.50000 0.90000 0.50000) + 4 V(56 55 66 67) M(0) UV(0.00000 0.50000 0.10000 0.50000 0.10000 0.60000 0.00000 0.60000) + 4 V(55 57 68 66) M(0) UV(0.10000 0.50000 0.20000 0.50000 0.20000 0.60000 0.10000 0.60000) + 4 V(57 58 69 68) M(0) UV(0.20000 0.50000 0.30000 0.50000 0.30000 0.60000 0.20000 0.60000) + 4 V(58 59 70 69) M(0) UV(0.30000 0.50000 0.40000 0.50000 0.40000 0.60000 0.30000 0.60000) + 4 V(59 60 71 70) M(0) UV(0.40000 0.50000 0.50000 0.50000 0.50000 0.60000 0.40000 0.60000) + 4 V(60 61 72 71) M(0) UV(0.50000 0.50000 0.60000 0.50000 0.60000 0.60000 0.50000 0.60000) + 4 V(61 62 73 72) M(0) UV(0.60000 0.50000 0.70000 0.50000 0.70000 0.60000 0.60000 0.60000) + 4 V(62 63 74 73) M(0) UV(0.70000 0.50000 0.80000 0.50000 0.80000 0.60000 0.70000 0.60000) + 4 V(63 64 75 74) M(0) UV(0.80000 0.50000 0.90000 0.50000 0.90000 0.60000 0.80000 0.60000) + 4 V(64 65 76 75) M(0) UV(0.90000 0.50000 1.00000 0.50000 1.00000 0.60000 0.90000 0.60000) + 4 V(67 66 77 78) M(0) UV(0.00000 0.60000 0.10000 0.60000 0.10000 0.70000 0.00000 0.70000) + 4 V(66 68 79 77) M(0) UV(0.10000 0.60000 0.20000 0.60000 0.20000 0.70000 0.10000 0.70000) + 4 V(68 69 80 79) M(0) UV(0.20000 0.60000 0.30000 0.60000 0.30000 0.70000 0.20000 0.70000) + 4 V(69 70 81 80) M(0) UV(0.30000 0.60000 0.40000 0.60000 0.40000 0.70000 0.30000 0.70000) + 4 V(70 71 82 81) M(0) UV(0.40000 0.60000 0.50000 0.60000 0.50000 0.70000 0.40000 0.70000) + 4 V(71 72 83 82) M(0) UV(0.50000 0.60000 0.60000 0.60000 0.60000 0.70000 0.50000 0.70000) + 4 V(72 73 84 83) M(0) UV(0.60000 0.60000 0.70000 0.60000 0.70000 0.70000 0.60000 0.70000) + 4 V(73 74 85 84) M(0) UV(0.70000 0.60000 0.80000 0.60000 0.80000 0.70000 0.70000 0.70000) + 4 V(74 75 86 85) M(0) UV(0.80000 0.60000 0.90000 0.60000 0.90000 0.70000 0.80000 0.70000) + 4 V(75 76 87 86) M(0) UV(0.90000 0.60000 1.00000 0.60000 1.00000 0.70000 0.90000 0.70000) + 4 V(78 77 88 89) M(0) UV(0.00000 0.70000 0.10000 0.70000 0.10000 0.80000 0.00000 0.80000) + 4 V(77 79 90 88) M(0) UV(0.10000 0.70000 0.20000 0.70000 0.20000 0.80000 0.10000 0.80000) + 4 V(79 80 91 90) M(0) UV(0.20000 0.70000 0.30000 0.70000 0.30000 0.80000 0.20000 0.80000) + 4 V(80 81 92 91) M(0) UV(0.30000 0.70000 0.40000 0.70000 0.40000 0.80000 0.30000 0.80000) + 4 V(81 82 93 92) M(0) UV(0.40000 0.70000 0.50000 0.70000 0.50000 0.80000 0.40000 0.80000) + 4 V(82 83 94 93) M(0) UV(0.50000 0.70000 0.60000 0.70000 0.60000 0.80000 0.50000 0.80000) + 4 V(83 84 95 94) M(0) UV(0.60000 0.70000 0.70000 0.70000 0.70000 0.80000 0.60000 0.80000) + 4 V(84 85 96 95) M(0) UV(0.70000 0.70000 0.80000 0.70000 0.80000 0.80000 0.70000 0.80000) + 4 V(85 86 97 96) M(0) UV(0.80000 0.70000 0.90000 0.70000 0.90000 0.80000 0.80000 0.80000) + 4 V(86 87 98 97) M(0) UV(0.90000 0.70000 1.00000 0.70000 1.00000 0.80000 0.90000 0.80000) + 4 V(89 88 99 100) M(0) UV(0.00000 0.80000 0.10000 0.80000 0.10000 0.90000 0.00000 0.90000) + 4 V(88 90 101 99) M(0) UV(0.10000 0.80000 0.20000 0.80000 0.20000 0.90000 0.10000 0.90000) + 4 V(90 91 102 101) M(0) UV(0.20000 0.80000 0.30000 0.80000 0.30000 0.90000 0.20000 0.90000) + 4 V(91 92 103 102) M(0) UV(0.30000 0.80000 0.40000 0.80000 0.40000 0.90000 0.30000 0.90000) + 4 V(92 93 104 103) M(0) UV(0.40000 0.80000 0.50000 0.80000 0.50000 0.90000 0.40000 0.90000) + 4 V(93 94 105 104) M(0) UV(0.50000 0.80000 0.60000 0.80000 0.60000 0.90000 0.50000 0.90000) + 4 V(94 95 106 105) M(0) UV(0.60000 0.80000 0.70000 0.80000 0.70000 0.90000 0.60000 0.90000) + 4 V(95 96 107 106) M(0) UV(0.70000 0.80000 0.80000 0.80000 0.80000 0.90000 0.70000 0.90000) + 4 V(96 97 108 107) M(0) UV(0.80000 0.80000 0.90000 0.80000 0.90000 0.90000 0.80000 0.90000) + 4 V(97 98 109 108) M(0) UV(0.90000 0.80000 1.00000 0.80000 1.00000 0.90000 0.90000 0.90000) + 4 V(100 99 110 111) M(0) UV(0.00000 0.90000 0.10000 0.90000 0.10000 1.00000 0.00000 1.00000) + 4 V(99 101 112 110) M(0) UV(0.10000 0.90000 0.20000 0.90000 0.20000 1.00000 0.10000 1.00000) + 4 V(101 102 113 112) M(0) UV(0.20000 0.90000 0.30000 0.90000 0.30000 1.00000 0.20000 1.00000) + 4 V(102 103 114 113) M(0) UV(0.30000 0.90000 0.40000 0.90000 0.40000 1.00000 0.30000 1.00000) + 4 V(103 104 115 114) M(0) UV(0.40000 0.90000 0.50000 0.90000 0.50000 1.00000 0.40000 1.00000) + 4 V(104 105 116 115) M(0) UV(0.50000 0.90000 0.60000 0.90000 0.60000 1.00000 0.50000 1.00000) + 4 V(105 106 117 116) M(0) UV(0.60000 0.90000 0.70000 0.90000 0.70000 1.00000 0.60000 1.00000) + 4 V(106 107 118 117) M(0) UV(0.70000 0.90000 0.80000 0.90000 0.80000 1.00000 0.70000 1.00000) + 4 V(107 108 119 118) M(0) UV(0.80000 0.90000 0.90000 0.90000 0.90000 1.00000 0.80000 1.00000) + 4 V(108 109 120 119) M(0) UV(0.90000 0.90000 1.00000 0.90000 1.00000 1.00000 0.90000 1.00000) + } +} +Eof diff --git a/script/KevinSystem/img/Default_Background_IceMountain_Spell01.png b/script/KevinSystem/img/Default_Background_IceMountain_Spell01.png new file mode 100644 index 0000000..119af7d Binary files /dev/null and b/script/KevinSystem/img/Default_Background_IceMountain_Spell01.png differ diff --git a/script/KevinSystem/img/Default_Background_IceMountain_Spell02.png b/script/KevinSystem/img/Default_Background_IceMountain_Spell02.png new file mode 100644 index 0000000..c5f0a8a Binary files /dev/null and b/script/KevinSystem/img/Default_Background_IceMountain_Spell02.png differ diff --git a/script/KevinSystem/img/Default_Effect.png b/script/KevinSystem/img/Default_Effect.png new file mode 100644 index 0000000..61b968d Binary files /dev/null and b/script/KevinSystem/img/Default_Effect.png differ diff --git a/script/KevinSystem/img/Default_MagicCircle.png b/script/KevinSystem/img/Default_MagicCircle.png new file mode 100644 index 0000000..0e0d6a1 Binary files /dev/null and b/script/KevinSystem/img/Default_MagicCircle.png differ diff --git a/script/KevinSystem/img/Default_Shot.png b/script/KevinSystem/img/Default_Shot.png new file mode 100644 index 0000000..4cacac2 Binary files /dev/null and b/script/KevinSystem/img/Default_Shot.png differ diff --git a/script/KevinSystem/img/Default_System.png b/script/KevinSystem/img/Default_System.png new file mode 100644 index 0000000..99f86c3 Binary files /dev/null and b/script/KevinSystem/img/Default_System.png differ diff --git a/script/KevinSystem/img/Default_SystemBackground.png b/script/KevinSystem/img/Default_SystemBackground.png new file mode 100644 index 0000000..975f560 Binary files /dev/null and b/script/KevinSystem/img/Default_SystemBackground.png differ diff --git a/script/KevinSystem/img/Default_SystemDigit.png b/script/KevinSystem/img/Default_SystemDigit.png new file mode 100644 index 0000000..4bb15dc Binary files /dev/null and b/script/KevinSystem/img/Default_SystemDigit.png differ diff --git a/script/KevinSystem/img/HUD1.png b/script/KevinSystem/img/HUD1.png new file mode 100644 index 0000000..833188e Binary files /dev/null and b/script/KevinSystem/img/HUD1.png differ diff --git a/script/KevinSystem/img/HUD2.png b/script/KevinSystem/img/HUD2.png new file mode 100644 index 0000000..0b613db Binary files /dev/null and b/script/KevinSystem/img/HUD2.png differ diff --git a/script/KevinSystem/img/HomosexualHUD.png b/script/KevinSystem/img/HomosexualHUD.png new file mode 100644 index 0000000..f70511e Binary files /dev/null and b/script/KevinSystem/img/HomosexualHUD.png differ diff --git a/script/KevinSystem/img/Kevin_Effect.png b/script/KevinSystem/img/Kevin_Effect.png new file mode 100644 index 0000000..7a31427 Binary files /dev/null and b/script/KevinSystem/img/Kevin_Effect.png differ diff --git a/script/KevinSystem/img/ThiccHUD.png b/script/KevinSystem/img/ThiccHUD.png new file mode 100644 index 0000000..9b71382 Binary files /dev/null and b/script/KevinSystem/img/ThiccHUD.png differ diff --git a/script/KevinSystem/img/ThiccHUD_JP.png b/script/KevinSystem/img/ThiccHUD_JP.png new file mode 100644 index 0000000..f6263ca Binary files /dev/null and b/script/KevinSystem/img/ThiccHUD_JP.png differ diff --git a/script/KevinSystem/img/lifebar.png b/script/KevinSystem/img/lifebar.png new file mode 100644 index 0000000..b016e5c Binary files /dev/null and b/script/KevinSystem/img/lifebar.png differ diff --git a/script/KevinSystem/img/lifebarOLD.png b/script/KevinSystem/img/lifebarOLD.png new file mode 100644 index 0000000..87e44c4 Binary files /dev/null and b/script/KevinSystem/img/lifebarOLD.png differ diff --git a/script/KevinSystem/img/lol.png b/script/KevinSystem/img/lol.png new file mode 100644 index 0000000..9193bb9 Binary files /dev/null and b/script/KevinSystem/img/lol.png differ diff --git a/script/KevinSystem/img/newitem.aseprite b/script/KevinSystem/img/newitem.aseprite new file mode 100644 index 0000000..845992f Binary files /dev/null and b/script/KevinSystem/img/newitem.aseprite differ diff --git a/script/KevinSystem/img/textbox.png b/script/KevinSystem/img/textbox.png new file mode 100644 index 0000000..c4ce329 Binary files /dev/null and b/script/KevinSystem/img/textbox.png differ diff --git a/script/KevinSystem/img/yo.png b/script/KevinSystem/img/yo.png new file mode 100644 index 0000000..eb069d3 Binary files /dev/null and b/script/KevinSystem/img/yo.png differ diff --git a/script/KevinSystem/kevin_system/ItemSoundLib.txt b/script/KevinSystem/kevin_system/ItemSoundLib.txt new file mode 100644 index 0000000..78f5f91 --- /dev/null +++ b/script/KevinSystem/kevin_system/ItemSoundLib.txt @@ -0,0 +1,34 @@ +// Sound effects for items go here. + +let itemlib = GetModuleDirectory() ~ "./script/KevinSystem/RyannSFX/ItemSFX/"; +let SFXVol = GetAreaCommonData("Config", "SEVol", 100) * 0.01; + +// Sound objects declarations + +let SpellSFX = ObjSound_Create(); +let LifeSFX = ObjSound_Create(); +let CancelSFX = ObjSound_Create(); +let RegularItemSFX = ObjSound_Create(); +let SpecialItemSFX = ObjSound_Create(); + +// Merge function that loads sounds and significantly decreases volume +// so the ears do not die from SFX overload. + +function LoadEx(targetobj, targetpath, targetvol){ + + ObjSound_Load(targetobj, targetpath); + ObjSound_SetVolumeRate(targetobj, targetvol * SFXVol); + ObjSound_SetSoundDivision(targetobj, SOUND_SE); + +} + +task _ItemSoundTask{ + + LoadEx(SpellSFX, itemlib ~ "bfxr_SpellExtend.wav", 100); + LoadEx(LifeSFX, itemlib ~ "bfxr_LifeExtend.wav", 100); + LoadEx(CancelSFX, itemlib ~ "bfxr_GetItemCancel.wav", 20); + LoadEx(RegularItemSFX, itemlib ~ "bfxr_GetItem1.wav", 50); + LoadEx(SpecialItemSFX, itemlib ~ "bfxr_GetItemSpecial.wav", 150); +} + +// Functions to load sounds in scripts diff --git a/script/KevinSystem/kevin_system/KevinSystem_Item.txt b/script/KevinSystem/kevin_system/KevinSystem_Item.txt new file mode 100644 index 0000000..ed8791f --- /dev/null +++ b/script/KevinSystem/kevin_system/KevinSystem_Item.txt @@ -0,0 +1,509 @@ +// Item script + +float widthSTG = GetStgFrameWidth(); +float heightSTG = GetStgFrameHeight(); + +float PIV = 0; + +let POINTER_PIV = LoadAreaCommonDataValuePointer("PIV", "currentvalue", 1000); + +let POINTER_CHAIN = LoadAreaCommonDataValuePointer("PIV", "ChainAmount", 1); +let POINTER_CHAINGAUGE = LoadAreaCommonDataValuePointer("PIV", "ChainGauge", 0); +let POINTER_SPECIALAMMO = LoadAreaCommonDataValuePointer("PIV", "SpecialAmmo", 100); +let POINTER_SPECIALCHECK = LoadAreaCommonDataValuePointer("PIV", "IsUsingSpecial", false); +let POINTER_CHAINCHECK = LoadAreaCommonDataValuePointer("PIV", "IsChaining", false); + +int SPECIAL_BOOST_COUNT = 0; + +float rateReduceNormal = 100/120; +float rateReduceCashin = 100/180; + +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" + +#include "./Kevin_ItemConst.txt" +#include "./Kevin_ItemLib.txt" +#include "./ItemSoundLib.txt" + +// Chain system: Crystals fill up your chain amount, up to a max of 64x +// When you use a bomb (IsBomb), items get cancelled into golden point items worth 10000 x Chain Amount (max 640000 per item) + +@Initialize{ + + SetAutoDeleteObject(true); + _ItemSoundTask(); + SetDefaultBonusItemEnable(false); + LoadItemData(GetCurrentScriptDirectory ~ "./Kevin_ItemData.txt"); + + SetAreaCommonData("ScriptID", "ItemID", GetOwnScriptID()); + //SetCommonDataPtr("ItemIDPtr", GetOwnScriptID()); + +} + +int objPlayer = GetPlayerObjectID(); +float tmpSpd = 0, tmpScl = 0, tmpMtp = 0; + +@MainLoop{ + + PIV = GetCommonDataPtr(POINTER_PIV, 1000); + + for each(item in GetItemIdInCircleA1(widthSTG/2, heightSTG/2, heightSTG)){ + + tmpSpd = ObjMove_GetSpeed(item); + tmpMtp = ObjItem_IsMoveToPlayer(item); + + if(tmpSpd >= 0){ + if (!tmpMtp && GetPlayerState() != STATE_DOWN){ + ObjItem_SetMoveToPlayer(item, true); + } + } + + if(tmpMtp) { + ObjMove_SetAngle(item, GetAngleToPlayer(item)); + ObjMove_SetAcceleration(item, 1); + ObjMove_SetMaxSpeed(item, 24); + } + + } + + yield; +} + +@Event +{ + alternative (GetEventType()) + case (EV_GET_ITEM){ + + let obj = GetEventArgument(0); + + alternative(obj) + + case(POINT_REGULAR){ + + AddScore(1000); + ObjSound_Play(CancelSFX); + SetCommonDataPtr(POINTER_SPECIALAMMO, min(100, GetCommonDataPtr(POINTER_SPECIALAMMO, 100)+0.1)); + SetCommonDataPtr(POINTER_PIV, GetCommonDataPtr(POINTER_PIV, 1000)+50); + + } + + case(POINT_BHESTIE) { AddScore(2*GetCommonDataPtr(POINTER_PIV, 10000)); ObjSound_Play(SpecialItemSFX);} + + // Rainbow point items give 10000 x Chain Counter + + case(POINT_GOLD_SMALL) { AddScore(GetCommonDataPtr(POINTER_CHAIN, 1)*GetCommonDataPtr(POINTER_PIV, 10000)); ObjSound_Play(SpecialItemSFX);} + + case(POINT_GOLD_MEDIUM) { AddScore(GetCommonDataPtr(POINTER_CHAIN, 1)*GetCommonDataPtr(POINTER_PIV, 10000)); ObjSound_Play(SpecialItemSFX);} + + case(POINT_GOLD_LARGE) { + + AddScore(GetCommonDataPtr(POINTER_PIV, 1000)); + ObjSound_Play(SpecialItemSFX); + + } + + case(POINT_CANCEL) { AddScore(0.05*GetCommonDataPtr(POINTER_PIV, 10000)); ObjSound_Play(CancelSFX);} + + case(EXTEND_LIFE) { AddScore(GetCommonDataPtr(POINTER_PIV, 10000)); SetPlayerLife(GetPlayerLife()+1); ObjSound_Play(SpellSFX);} + + case(EXTEND_SPELL) { AddScore(GetCommonDataPtr(POINTER_PIV, 10000)); SetPlayerSpell(GetPlayerSpell()+1); ObjSound_Play(SpecialItemSFX);} + + // CHAIN ITEM + + case(PIV_250) { + + if (GetCommonDataPtr(POINTER_SPECIALCHECK, false) == true){ + + if(SPECIAL_BOOST_COUNT <= 90 && GetCommonDataPtr(POINTER_CHAIN, 1) >= 48){ + + SetCommonDataPtr(POINTER_CHAINGAUGE, min(100, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)+ rateReduceCashin * 5 * (1 - SPECIAL_BOOST_COUNT/90))); + SPECIAL_BOOST_COUNT++; + + } + + + } + + else{ + + if(GetCommonDataPtr(POINTER_CHAIN, 1) <= 1){ + + SetCommonDataPtr(POINTER_CHAINGAUGE, 100); + + } + + SetCommonDataPtr(POINTER_CHAIN, min(64, GetCommonDataPtr(POINTER_CHAIN, 1)+0.15)); + SetCommonDataPtr(POINTER_CHAINGAUGE, min(100, GetCommonDataPtr(POINTER_CHAINGAUGE, 0)+ rateReduceNormal * 20)); + + SPECIAL_BOOST_COUNT = 0; + + } + + + } + + case(PIV_500) { SetCommonDataPtr(POINTER_PIV, GetCommonDataPtr(POINTER_PIV, 10000)+500);} + + case(SPECIAL_AMMO) { + + SetCommonDataPtr(POINTER_SPECIALAMMO, min(100, GetCommonDataPtr(POINTER_SPECIALAMMO, 100)+0.2)); + + } + + } + + case (EV_DELETE_SHOT_TO_ITEM){ + + float[] position = GetEventArgument(1); + + if(GetCommonDataPtr(POINTER_SPECIALCHECK, true) == true && IsPlayerSpellActive() != true && GetPlayerState() == STATE_NORMAL){ + CreateScoreItem(POINT_GOLD_LARGE, position[0], position[1]); + } // Kouryuu special weapon + else{ + CreateScoreItem(POINT_REGULAR, position[0], position[1]); + } // Death or bomb + + } + + case (EV_CANCEL_ITEM) { + + let obj = GetEventArgument(0); + let type = GetEventArgument(1); + + //ObjItem_SetMoveToPlayer(obj, false); + ObjMove_CancelMovement(obj); + + //_CancelHandling(obj, type); + + } + + case (EV_COLLECT_ITEM){ + + let obj = GetEventArgument(0); + let type = GetEventArgument(1); + let typeCollect = GetEventArgument(2); + + //WriteLog(type); + //_MoveToPlayer(obj, type, typeCollect); // Separate task is used to move the object to the player at customized speeds. + + } + + // Drops point items depending on how close you were to the enemy when you killed them. + /* + Event arguments: + + 0: PlayerID + 1: EnemyID + 2: Minimum number of point items + 3: Maximum number of point items + + */ + + case(EV_DROP_POINT_ENEMY){ + + _DropPointItem(GetEventArgument(0), GetEventArgument(1), GetEventArgument(2), GetEventArgument(3), GetEventArgument(4)); + + } + + case(EV_DROP_PIV_ENEMY){ + + //_DropPIVItemEnemy(GetEventArgument(0), GetEventArgument(1), GetEventArgument(2), GetEventArgument(3), GetEventArgument(4)); + + } + + case(EV_DROP_AMMO_ENEMY){ + + //_DropAmmoItemEnemy(GetEventArgument(0), GetEventArgument(1), GetEventArgument(2), GetEventArgument(3), GetEventArgument(4)); + + } + + // Event arguments: Enemy X, Enemy Y, Item Drop Amount, Item Drop Type + + case(EV_SINGLE_ITEM_DROP){ + + loop(GetEventArgument(2)){ + CreateScoreItem(GetEventArgument(3), GetEventArgument(0)+rand(-100, 100), GetEventArgument(1)+rand(-100, 100)); + } + + } + + case(EV_DROP_EXTEND){ + CreateExtendItem(EXTEND_LIFE, GetEventArgument(0), GetEventArgument(1)); + } + +} + +task _CancelHandling(int IDItem, int typeItem){ + + ObjMove_CancelMovement(IDItem); + + while(GetPlayerState() != STATE_NORMAL){yield;} + + _MoveToPlayer(IDItem, typeItem, 0); + +} + +// Timer is counted in frames (60 frames = 1 second) + +task _DropPointItem(float[] posEnm, float killTimer, float maxTimer, float pointMin, float pointMax){ + + // If the player kills enemy within maxTimer, the enemy drops the maximum amount of point items + + float pointFinal = Interpolate_Smooth(pointMax, pointMin, min(1, killTimer/maxTimer)); + + WriteLog(killTimer/maxTimer); + + if (GetCommonDataPtr(POINTER_CHAINCHECK, false) == true){ + + loop(pointFinal){ + + CreateScoreItem(POINT_GOLD_LARGE, posEnm[0]+rand(-60, 60), posEnm[1]+rand(-60, 60)); + + } + + } + + else{ + + loop(pointFinal){ + + CreateScoreItem(POINT_REGULAR, posEnm[0]+rand(-60, 60), posEnm[1]+rand(-60, 60)); + + } + + } + + if(GetAreaCommonData("Config", "EffectCut", 0) >= 1){} + else{_ScorePopup(posEnm[0], posEnm[1], "POINT", pointFinal);} + + return; + + +} + +task _DropPIVItemEnemy(int IDPlayer, float[] posEnm, int pointMin, int pointMax, int bestDist){ + + // If the player is within at MOST "bestDist" from the enemy, the enemy drops the maximum amount of PIV items + + float curDist = hypot(posEnm[0]-ObjMove_GetX(IDPlayer), posEnm[1]-ObjMove_GetY(IDPlayer)); + + int pointFinal = Interpolate_Smooth(pointMin, pointMax, min(1, bestDist/curDist)); + //WriteLog(pointFinal); + + loop(pointFinal){ + + CreatePIVItem(PIV_250, posEnm[0]+rand(-60, 60), posEnm[1]+rand(-60, 60)); + + } + + /* + if(GetCommonDataPtr(EFFECTCUT_PTR, 0) >= 1){} + else{_ScorePopup(posEnm[0], posEnm[1], "PIV", pointFinal);} + */ + + return; + +} + +task _DropAmmoItemEnemy(int IDPlayer, float[] posEnm, int pointMin, int pointMax, int bestDist){ + + // If the player is within at MOST "bestDist" from the enemy, the enemy drops the maximum amount of PIV items + + float curDist = hypot(posEnm[0]-ObjMove_GetX(IDPlayer), posEnm[1]-ObjMove_GetY(IDPlayer)); + + int pointFinal = Interpolate_Smooth(pointMin, pointMax, min(1, bestDist/curDist)); + //WriteLog(pointFinal); + + loop(pointFinal){ + + CreateAmmoItem(posEnm[0]+rand(-60, 60), posEnm[1]+rand(-60, 60)); + + } + + if(GetCommonDataPtr(EFFECTCUT_PTR, 0) >= 1){} + else{_ScorePopup(posEnm[0], posEnm[1], "AMMO", pointFinal);} + + return; + + +} + +task _MoveToPlayer(obj, type, typeCollect){ + + ObjItem_SetAutoDelete(obj, true); + ObjMove_SetAcceleration(obj, 1); + //ObjMove_SetMaxSpeed(obj, 2); + + // The max speed of movement differs based on item. + alternative(type) + + case(POINT_CANCEL) { ObjMove_SetMaxSpeed(obj, 23); } + + case(PIV_100) { ObjMove_SetMaxSpeed(obj, 18); } + case(PIV_250) { ObjMove_SetMaxSpeed(obj, 18); } + case(PIV_500) { ObjMove_SetMaxSpeed(obj, 18); } + + case(POINT_REGULAR) { ObjMove_SetMaxSpeed(obj, 20); } + case(POINT_RAINBOW) { ObjMove_SetMaxSpeed(obj, 20); } + case(POINT_BHESTIE) { ObjMove_SetMaxSpeed(obj, 20); } + others { ObjMove_SetMaxSpeed(obj, 25); } + + while (!Obj_IsDeleted(obj)) { + ObjMove_SetAngle(obj, GetAngleToPlayer(obj)); + //WriteLog(ObjMove_GetSpeed(obj)); + yield; + } + +} + + +// Text popups. When enemy is defeated, text objects appear showing the number of PIV and point items collected. + +function CreateTextObject( + float mx, my, size, + string text, font, + int colorTop, colorBottom, + int borderColor, borderWidth, + int renderPriority + ){ + + let obj = ObjText_Create(); + ObjText_SetText(obj, text); + ObjText_SetFontSize(obj, size); + ObjText_SetFontType(obj, font); + ObjText_SetFontColorTop(obj, colorTop); + ObjText_SetFontColorBottom(obj, colorBottom); + ObjText_SetFontBorderType(obj, BORDER_FULL); + ObjText_SetFontBorderColor(obj, borderColor); + ObjText_SetFontBorderWidth(obj, borderWidth); + Obj_SetRenderPriorityI(obj, renderPriority); + ObjRender_SetX(obj, mx); + ObjRender_SetY(obj, my); + return obj; + +} + +task _ScorePopup(float enmX, float enmY, string type, int itemNum){ + + if (itemNum <= 0){return;} + + float offset = 72; // Vertical space between the 2 scoretexts + float time = 30; // Time that the text objects (appear+)last on screen + float timeDisappear = 15; // Fade time + float size = 40; + float yDes = 60; // Destination text object moves to, relative to enmY + string font = "GravityRegular5"; + string font2 = "GravityBold8"; + float borderSize = 6; + + if (type == "POINT") + { + + int pointText = CreateTextObject( + enmX, enmY, size, + IntToString(itemNum * 10000) ~ " x " ~ IntToString(GetCommonDataPtr(POINTER_CHAIN, 1)), font, + 0x7699FF, 0xFFFFFF, + 0x2A00C0, borderSize, + 42 + ); + + ObjText_SetHorizontalAlignment(pointText, ALIGNMENT_CENTER); + + if (GetCommonDataPtr(POINTER_CHAINCHECK, false) == true){ + + ObjText_SetFontBorderColor(pointText, 0xFF9700); + ObjText_SetFontColorTop(pointText, 0xFFD69C); + ObjText_SetFontSize(pointText, 56); + ObjText_SetFontType(pointText, font2); + ObjText_SetText(pointText, IntToString(itemNum * PIV)); + + } + + else{ + + ObjText_SetFontBorderColor(pointText, 0x2A00C0); + ObjText_SetFontColorTop(pointText, 0x7699FF); + ObjText_SetFontSize(pointText, 40); + ObjText_SetFontType(pointText, font); + ObjText_SetText(pointText, IntToString(itemNum * 1000) ~ "[r][font tc=(255, 223, 143) oz=4 oc=(123, 45, 23) bc=(219, 163, 21) oy=12 sz=25]+" ~ IntToString(itemNum * 50) ~ " VALUE"); + + } + + ascent(i in 0..time){ + ObjRender_SetY(pointText, Interpolate_Decelerate(enmY, enmY-yDes, i/time)); + yield; + } + + ascent(i in 0..timeDisappear){ + ObjRender_SetAlpha(pointText, Interpolate_Decelerate(255, 0, i/timeDisappear)); + yield; + } + Obj_Delete(pointText); + } + + else if (type == "PIV") + { + int pivText = CreateTextObject( + enmX, enmY+offset, size, + "x" ~ IntToString(itemNum), font, + 0xFFB4EC, 0xFFFFFF, + 0xB200AD, borderSize, + 42 + ); + + ObjText_SetHorizontalAlignment(pivText, ALIGNMENT_CENTER); + + if (GetCommonDataPtr(POINTER_CHAINCHECK, false) == true){ + Obj_SetVisible(pivText, false); + } + else{ + Obj_SetVisible(pivText, true); + } + + ascent(i in 0..time){ + ObjRender_SetY(pivText, Interpolate_Decelerate(enmY+offset, enmY+offset-yDes, i/time)); + yield; + } + + ascent(i in 0..timeDisappear){ + ObjRender_SetAlpha(pivText, Interpolate_Decelerate(255, 0, i/timeDisappear)); + yield; + } + + Obj_Delete(pivText); + } + + + else if (type == "AMMO") + { + int pivText = CreateTextObject( + enmX, enmY+offset, size, + "+" ~ rtos("00.00", itemNum*0.2) ~ " [font ox=-24 oy=27 sz=45]AMMO", font, + 0xFFB4EC, 0xFFFFFF, + 0xF63357, borderSize, + 42 + ); + + ObjText_SetHorizontalAlignment(pivText, ALIGNMENT_CENTER); + + if (GetCommonDataPtr(POINTER_CHAINCHECK, false) == true){ + Obj_SetVisible(pivText, false); + } + else{ + Obj_SetVisible(pivText, true); + } + + ascent(i in 0..time){ + ObjRender_SetY(pivText, Interpolate_Decelerate(enmY+offset, enmY+offset-yDes, i/time)); + yield; + } + + ascent(i in 0..timeDisappear){ + ObjRender_SetAlpha(pivText, Interpolate_Decelerate(255, 0, i/timeDisappear)); + yield; + } + + Obj_Delete(pivText); + } + + else{} +} diff --git a/script/KevinSystem/kevin_system/Kevin_EffectLib.dnh b/script/KevinSystem/kevin_system/Kevin_EffectLib.dnh new file mode 100644 index 0000000..986a95f --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_EffectLib.dnh @@ -0,0 +1,115 @@ + +//let imgEffect = dirCurrent ~ "./img/Kevin_Effect.png"; +int PetalEffect = ObjParticleList_Create(OBJ_PARTICLE_LIST_2D); + +task InitEffect(){ + _EffectListPreRender(PetalEffect, imgEffect, [0, 0, 256, 256]); +} + +let imgEffect = dirCurrent ~ "./img/Kevin_Effect.png"; + +// Enemy deletion/explosion effects. + +// This particle list is used for all instances of the effect. + +task _EffectListPreRender( + int targetList, + texture, int[] rect + ){ + + ObjPrim_SetTexture(targetList, texture); + + Obj_SetRenderPriorityI(targetList, 39); + ObjPrim_SetPrimitiveType(targetList, PRIMITIVE_TRIANGLELIST); + ObjPrim_SetVertexCount(targetList, 4); + + ObjRender_SetBlendType(targetList, BLEND_ALPHA); + + // Left-top, right-top, left-bottom, right-bottom + + ObjPrim_SetVertexUVT(targetList, 0, rect[0], rect[1]); + ObjPrim_SetVertexUVT(targetList, 1, rect[2], rect[1]); + ObjPrim_SetVertexUVT(targetList, 2, rect[0], rect[3]); + ObjPrim_SetVertexUVT(targetList, 3, rect[2], rect[3]); + + // Vertex positions are offset with deltas so that the sprite is centered + + float dU = (rect[2] - rect[0])/2; + float dV = (rect[3] - rect[1])/2; + + ObjPrim_SetVertexPosition(targetList, 0, -dU, -dV, 1); + ObjPrim_SetVertexPosition(targetList, 1, dU, -dV, 1); + ObjPrim_SetVertexPosition(targetList, 2, -dU, dV, 1); + ObjPrim_SetVertexPosition(targetList, 3, dU, dV, 1); + + ObjPrim_SetVertexIndex(targetList, [0, 1, 2, 1, 2, 3]); + + } + +// Enemy go Boom + +/* +5 flower petals appear from the enemy and spin outwards. +Their angle constantly changes and their alpha lowers over time. +*/ + +task _ExplosionEffect(float enmX, float enmY, int targetList){ + + int i = 0; + int effectLength = 45; + int effectNum = 5; + int dir = 1; + + Obj_SetRenderPriorityI(targetList, 40); + //TExplosionA(enmX, enmY, 255/effectLength, 9/effectLength); + + /*ascent(i in 0..effectNum){ + _CreatePetal(prand(5, 10)*dir, prand(5, 10)*dir, prand(0, 360)); + dir *= -1; + //_CreatePetal(prand(50, 80), prand(-80, -50), prand(0, 360)); + }*/ + + _CreatePetal(prand(8, 11), prand(-8, -11), prand(0, 360)); + _CreatePetal(prand(-11, -8), prand(-2, 2), prand(0, 360)); + _CreatePetal(prand(8, 8), prand(-2, 2), prand(0, 360)); + _CreatePetal(prand(-11, -8), prand(8, 11), prand(0, 360)); + _CreatePetal(prand(8, 11), prand(8, 11), prand(0, 360)); + + ObjSound_Play(sfxBoom); + + // Create a petal with: + // x offset every frame, y offset every frame + + task _CreatePetal(float spdX, float spdY, float baseAng){ + + float x = enmX, y = enmY; + let x_speed = spdX; + let y_speed = spdY; + let z_add = prand(-5, 5); + + ascent(i in 0..effectLength){ + _PetalMovement(Interpolate_Decelerate(1.5, 0.5, i/effectLength), Interpolate_Decelerate(255, 0, i/effectLength)); + yield; + } + + task _PetalMovement(scale, alpha){ + + ObjParticleList_SetScale(targetList, scale); + ObjParticleList_SetAngleZ(targetList, baseAng); + ObjParticleList_SetPosition(targetList, x, y, 1); + ObjParticleList_SetAlpha(targetList, alpha); + + //Submits the current data to an instance, cleared every frame. + ObjParticleList_AddInstance(targetList); + + x += x_speed; + y += y_speed; + baseAng += z_add; + + yield; + + } + + } + +} \ No newline at end of file diff --git a/script/KevinSystem/kevin_system/Kevin_EndScene.txt b/script/KevinSystem/kevin_system/Kevin_EndScene.txt new file mode 100644 index 0000000..ebbb573 --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_EndScene.txt @@ -0,0 +1,263 @@ +//一時停止中スクリプト + +#include "script/KevinSystem/GeneralSoundLib.txt" + +int STGWIDTH = GetStgFrameWidth(); +int STGHEIGHT = GetStgFrameHeight(); + +@Initialize +{ + _SoundTask(); + ExtendSFX; + SetAutoDeleteObject(true); + TBackgroundNew(0, 0); + TMenu(); +} + +@MainLoop +{ + yield; +} + +@Finalize +{ +} + + +task TBackgroundNew(renderX, renderY){ + + let objText = ObjText_Create(); + ObjText_SetText(objText, ["Thank you for playing!", "このゲームを遊ぶをありがとうございました!"][GetCommonData("Language", 0)]); + ObjText_SetFontSize(objText, [38, 45][GetCommonData("Language", 0)]); + ObjText_SetFontType(objText, "コーポレート・ロゴ(ラウンド) ver2 Bold"); + + //ObjText_SetMaxWidth(objText, GetScreenWidth/2); + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER); + + ObjText_SetFontBold(objText, true); + ObjText_SetFontColorTop(objText, 255, 255, 255); + ObjText_SetFontColorBottom(objText, 255, 255, 255); + ObjText_SetFontBorderType(objText, BORDER_FULL); + ObjText_SetFontBorderColor(objText, 0x7D39D9); + ObjText_SetFontBorderWidth(objText, 2); + Obj_SetRenderPriorityI(objText, 10); + ObjRender_SetX(objText, GetScreenWidth/2); + ObjRender_SetY(objText, 7.5*STGHEIGHT/8); + + let obj = ObjPrim_Create(OBJ_SPRITE_2D); + Obj_SetRenderPriorityI(obj, 1); + + let currentFrameTexture = GetTransitionRenderTargetName(); + + ObjPrim_SetTexture(obj, currentFrameTexture); + ObjSprite2D_SetSourceRect(obj, 0, 0, GetScreenWidth(), GetScreenHeight()); + ObjSprite2D_SetDestRect(obj, 0, 0, GetScreenWidth(), GetScreenHeight()); + + ObjRender_SetColor(obj, 0x593DA3); + +} + +task TBackground +{ + task TVertex(var index, var left, var top, var right, var bottom) + { + ObjPrim_SetVertexPosition(obj, index + 0, left, top, 0); + ObjPrim_SetVertexPosition(obj, index + 1, left, bottom, 0); + ObjPrim_SetVertexPosition(obj, index + 2, right, top, 0); + ObjPrim_SetVertexPosition(obj, index + 3, right, top, 0); + ObjPrim_SetVertexPosition(obj, index + 4, left, bottom, 0); + ObjPrim_SetVertexPosition(obj, index + 5, right, bottom, 0); + + ObjPrim_SetVertexUVT(obj, index + 0, left, top); + ObjPrim_SetVertexUVT(obj, index + 1, left, bottom); + ObjPrim_SetVertexUVT(obj, index + 2, right, top); + ObjPrim_SetVertexUVT(obj, index + 3, right, top); + ObjPrim_SetVertexUVT(obj, index + 4, left, bottom); + ObjPrim_SetVertexUVT(obj, index + 5, right, bottom); + + //STGシーン内のみアニメーション + if(left >= 341 && right <= 937 && top >= 45 && bottom <= 677) + { + let alpha = 255; + while(alpha >= 128) + { + ObjPrim_SetVertexAlpha(obj, index + 0, alpha); + ObjPrim_SetVertexAlpha(obj, index + 1, alpha/2); + ObjPrim_SetVertexAlpha(obj, index + 2, alpha/2); + ObjPrim_SetVertexAlpha(obj, index + 3, alpha/2); + ObjPrim_SetVertexAlpha(obj, index + 4, alpha/2); + ObjPrim_SetVertexAlpha(obj, index + 5, alpha); + alpha -= 255 / frame; + + yield; + } + } + } + + //分割設定 + let frame = 30; + let countH = 20; //分割数 + let countV = 30; + let width = 1280 / countH; + let height = 720 / countV; + let target = GetTransitionRenderTargetName(); + let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D); //2D頂点ブジェクト生成 + ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLELIST); + ObjPrim_SetVertexCount(obj, countH * countV * 6); + Obj_SetRenderPriorityI(obj, 0); //描画優先度を設定 + ObjPrim_SetTexture(obj, target); //テクスチャを設定 + + ascent(ix in 0.. countH) + { + ascent(iy in 0.. countV) + { + let index = (ix + iy * countH) * 6; + let left = ix * width; + let right = left + width; + let top = iy * height; + let bottom = top + height; + TVertex(index, left, top, right, bottom); + } + } + +} +task TMenu +{ + let selectIndex = 0;//選択位置 + function TMenuItem(let index, let mx, let my, let text) + { + function CreateTextObject(let mx, let my, let text) + { + let obj = ObjText_Create(); + ObjText_SetText(obj, text); + ObjText_SetFontSize(obj, 50); + ObjText_SetFontType(obj, "GravityRegular5"); + ObjText_SetFontBold(obj, true); + ObjText_SetHorizontalAlignment(obj, ALIGNMENT_CENTER); + //ObjText_SetMaxWidth(obj, STGWIDTH); + ObjText_SetFontColorTop(obj, 155, 45, 175); + ObjText_SetFontColorBottom(obj, 200, 80, 255); + ObjText_SetFontBorderType(obj, BORDER_FULL); + ObjText_SetFontBorderColor(obj, 255, 255, 255); + ObjText_SetFontBorderWidth(obj, 3.5); + Obj_SetRenderPriorityI(obj, 10); + ObjRender_SetX(obj, mx); + ObjRender_SetY(obj, my); + return obj; + } + + let objText = CreateTextObject(mx, my, text); + let objSelect = CreateTextObject(mx, my, text); + ObjRender_SetBlendType(objSelect, BLEND_ADD_RGB); + + async{ + loop + { + Obj_SetVisible(objSelect, index == selectIndex); + yield; + } + } + + return objText; + } + + //メニュー配置 + + let textchoices = ["THE END(?)"]; + int x = prand_int(0, length(textchoices)-1); + let objText = ObjText_Create(); + ObjText_SetText(objText, textchoices[x]); + ObjText_SetFontSize(objText, 72); + ObjText_SetFontType(objText, "GravityBold8"); + + //ObjText_SetMaxWidth(objText, STGWIDTH); + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER); + + ObjText_SetFontBold(objText, true); + ObjText_SetFontColorTop(objText, 75, 255, 255); + ObjText_SetFontColorBottom(objText, 180, 255, 255); + ObjText_SetFontBorderType(objText, BORDER_FULL); + ObjText_SetFontBorderColor(objText,0, 0, 0); + ObjText_SetFontBorderWidth(objText, 3); + Obj_SetRenderPriorityI(objText, 10); + ObjRender_SetX(objText, GetScreenWidth/2); + ObjRender_SetY(objText, 75); + + let mx = GetScreenWidth/2; + let my = GetScreenHeight/4; + let texts = ["SAVE REPLAY", "TITLE", "RESTART"]; + var countMenu = length(texts); + ascent(var iText in 0 .. countMenu) + { + int text = TMenuItem(iText, mx, my, texts[iText]); + my += 75; + } + + //キー状態がリセットされるまで待機 + while(GetVirtualKeyState(VK_PAUSE) != KEY_FREE){yield;} + + //メニュー選択処理 + let frameKeyHold = 0;//キー押しっぱなしフレーム数 + //PauseGameSFX; + + function CheckShotRelease { + return (GetVirtualKeyState(VK_OK) == KEY_HOLD); + } + + int countA = 0; + + loop + { + //決定 + if(CheckShotRelease){yield; continue;} + + if(GetVirtualKeyState(VK_OK) == KEY_PUSH) + { + let listResult = [RESULT_SAVE_REPLAY, RESULT_END, RESULT_RETRY]; + SetScriptResult(listResult[selectIndex]); + CloseScript(GetOwnScriptID()); + return; + } + + //カーソル移動 + if(GetVirtualKeyState(VK_UP) == KEY_PUSH) + { + selectIndex--; + } + else if(GetVirtualKeyState(VK_DOWN) == KEY_PUSH) + { + selectIndex++; + } + else if(GetVirtualKeyState(VK_UP) == KEY_HOLD) + { + frameKeyHold++; + if(frameKeyHold == 30 || (frameKeyHold > 30 && (frameKeyHold % 10 == 0))) + { + selectIndex--; + } + } + else if(GetVirtualKeyState(VK_DOWN) == KEY_HOLD) + { + frameKeyHold++; + if(frameKeyHold == 30 || (frameKeyHold > 30 && (frameKeyHold % 10 == 0))) + { + selectIndex++; + } + } + else + { + frameKeyHold = 0; + } + + if(selectIndex < 0) + { + selectIndex = countMenu - 1; + } + else + { + selectIndex %= countMenu; + } + + yield; + } +} \ No newline at end of file diff --git a/script/KevinSystem/kevin_system/Kevin_ItemConst.txt b/script/KevinSystem/kevin_system/Kevin_ItemConst.txt new file mode 100644 index 0000000..c7f6f9f --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_ItemConst.txt @@ -0,0 +1,18 @@ + +const POINT_REGULAR = 1; +const POINT_RAINBOW = 2; +const POINT_BHESTIE = 3; +const POINT_CANCEL = 4; + +const EXTEND_LIFE = 5; +const EXTEND_SPELL = 6; + +const PIV_100 = 7; +const PIV_250 = 8; +const PIV_500 = 9; +const FRAGMENT_SPELL = 10; + +const POINT_GOLD_SMALL = 11; +const POINT_GOLD_MEDIUM = 12; +const POINT_GOLD_LARGE = 13; +const SPECIAL_AMMO = 14; diff --git a/script/KevinSystem/kevin_system/Kevin_ItemData.txt b/script/KevinSystem/kevin_system/Kevin_ItemData.txt new file mode 100644 index 0000000..2dff3d0 --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_ItemData.txt @@ -0,0 +1,28 @@ +#UserItemData + +item_image = "./../img/yo.png" + +ItemData { id=1 rect=(576, 256, 608, 288) } // Regular Point Item (PIV) + +ItemData { id=2 rect=(384,128,512,256) } // Homosexual Point Item (PIV * 2) +ItemData { id=3 rect=(256,128,384,256) } // Bhestie Point Item (PIV * 2, 25% chance of drop) +ItemData { id=4 rect=(512,0,640,128) } // Cancel Item (PIV * O.2), erase bullets via bombs + +ItemData { id=5 rect=(0,256,128,384) } // 1-up Item +ItemData { id=6 rect=(128,256,256,384) } // Spell Item + +ItemData { id=7 rect=(256,384,384,512) fixed_angle = false angular_velocity = 3} // Green PIV Item (+100) +ItemData { id=8 rect=(512, 256, 576, 320) fixed_angle = false angular_velocity = 3} // Pink PIV Item (+250) +ItemData { id=9 rect=(384,256,512,384) fixed_angle = false angular_velocity = 3} // Gold PIV Item (+500) +ItemData { id=10 rect=(128,384,256,512) } // Spell Piece + +// New point items + +ItemData { id=11 rect=(608, 256, 640, 288) } +ItemData { id=12 rect=(640, 256, 704, 320) } + +ItemData { id=13 rect=(576, 320, 640, 384) } // Large gold item (NARUMI_STG) + +// Special ammo item + +ItemData { id=14 rect=(576, 288, 608, 320) } \ No newline at end of file diff --git a/script/KevinSystem/kevin_system/Kevin_ItemLib.txt b/script/KevinSystem/kevin_system/Kevin_ItemLib.txt new file mode 100644 index 0000000..83d2481 --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_ItemLib.txt @@ -0,0 +1,173 @@ +// Valid types: PIV_100, PIV_250, PIV_500 + +float universalItemAlpha = GetAreaCommonData("Config", "ItemOpacity", 60); + +function CreatePIVItem(itemtype, x, y){ + + let PIVItem = CreateItemU1(itemtype, x, y, 0); + ObjItem_SetDefaultCollectMovement(PIVItem, false); + ObjItem_SetAutoDelete(PIVItem, false); + + ObjMove_SetAngle(PIVItem, 90); + ObjMove_SetSpeed(PIVItem, -10); + ObjMove_SetAcceleration(PIVItem, 1); + ObjMove_SetMaxSpeed(PIVItem, 0); + + ObjItem_SetIntersectionRadius(PIVItem, 60); + + ObjRender_SetScaleXYZ(PIVItem, 2); + ObjRender_SetAlpha(PIVItem, 255*(universalItemAlpha/100)); + + return PIVItem; +} + +function CreateAmmoItem(x, y){ + + let Item = CreateItemU1(SPECIAL_AMMO, x, y, 0); + ObjItem_SetDefaultCollectMovement(Item, false); + ObjItem_SetAutoDelete(Item, false); + + ObjMove_SetAngle(Item, 90); + ObjMove_SetSpeed(Item, -10); + ObjMove_SetAcceleration(Item, 1); + ObjMove_SetMaxSpeed(Item, 0); + + ObjItem_SetIntersectionRadius(Item, 60); + + ObjRender_SetScaleXYZ(Item, 3); + ObjRender_SetAlpha(Item, 255*(universalItemAlpha/100)); + + return Item; +} + +// Valid types: POINT_REGULAR, POINT_BHESTIE, POINT_RAINBOW +function CreateScoreItem(itemtype, x, y){ + + let ScoreItem = CreateItemU1(itemtype, x + rand(-60, 60), y + rand(-60, 60), 0); + ObjItem_SetDefaultCollectMovement(ScoreItem, false); + ObjItem_SetAutoDelete(ScoreItem, false); + + ObjItem_SetAutoCollectEnableFlags(ScoreItem, ITEM_AUTOCOLLECT_ALL); + ObjMove_SetAngle(ScoreItem, 90); + ObjMove_SetSpeed(ScoreItem, -20); + ObjMove_SetAcceleration(ScoreItem, 1); + ObjMove_SetMaxSpeed(ScoreItem, 6); + + ObjItem_SetIntersectionRadius(ScoreItem, 64); + ObjItem_SetRenderScoreEnable(ScoreItem, false); + + ObjRender_SetAlpha(ScoreItem, 255*(universalItemAlpha/100)); + ObjRender_SetScaleXYZ(ScoreItem, 3); + + /* + if(itemtype == POINT_RAINBOW){ + + if(LoadAreaCommonDataValuePointer("PIV", "ChainGauge", 0) <= 32){ + ObjSprite2D_SetSourceRect(ScoreItem, 608, 256, 640, 288); + } + + else if(LoadAreaCommonDataValuePointer("PIV", "ChainGauge", 0) > 32 && LoadAreaCommonDataValuePointer("PIV", "ChainGauge", 0) < 64){ + ObjSprite2D_SetSourceRect(ScoreItem, 640, 256, 704, 320); + } + + else{ + ObjSprite2D_SetSourceRect(ScoreItem, 704, 256, 768, 320); + } + + } + */ + + return ScoreItem; +} + +function CreateCancelItem(x, y){ + + let CancelItem = CreateItemU1(POINT_CANCEL, x, y, 0); + ObjItem_SetDefaultCollectMovement(CancelItem, false); + + /*async{ + wait(45); + ObjItem_SetMoveToPlayer(CancelItem, true); + ObjMove_SetMaxSpeed(CancelItem, 24); + }*/ + + ObjItem_SetAutoCollectEnableFlags(CancelItem, ITEM_AUTOCOLLECT_ALL); + ObjItem_SetRenderScoreEnable(CancelItem, false); + + ObjItem_SetIntersectionRadius(CancelItem, 60); + + ObjRender_SetScaleXYZ(CancelItem, 0.6, 0.6, 1); + ObjRender_SetAlpha(CancelItem, 255*(universalItemAlpha/100)); + + async{ + while(!Obj_IsDeleted(CancelItem)){ + float angz = ObjRender_GetAngleZ(CancelItem); + ObjRender_SetAngleZ(CancelItem, angz+2); + yield; + } + } + + return CancelItem; + +} +// Valid types: EXTEND_LIFE, EXTEND_SPELL +function CreateExtendItem(itemtype, x, y){ + + let ExtendItem = CreateItemU2(itemtype, x, y, x, y-125, 0); + ObjItem_SetDefaultCollectMovement(ExtendItem, false); + //ObjItem_SetMoveToPlayer(ExtendItem, true); + ObjItem_SetAutoCollectEnableFlags(ExtendItem, ITEM_AUTOCOLLECT_ALL); + + ObjMove_SetAngle(ExtendItem, 90); + ObjMove_SetSpeed(ExtendItem, -20); + ObjMove_SetAcceleration(ExtendItem, 1); + ObjMove_SetMaxSpeed(ExtendItem, 0); + + ObjRender_SetScaleXYZ(ExtendItem, 1.5, 1.5, 1); + Obj_SetRenderPriorityI(ExtendItem, 49); + ObjItem_SetAutoDelete(ExtendItem, false); + + /*async{ + wait(30); + ObjItem_SetMoveToPlayer(ExtendItem, true); + //ObjMove_SetMaxSpeed(CancelItem, 24); + }*/ + + return ExtendItem; +} + +// Summoning the actual items + +function NonspellItemDrop(scene, x, y){ + + if(ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SHOOTDOWN_COUNT) == 0){ + loop(14){ + CreateScoreItem(POINT_REGULAR, x+rand(-75, 75), y+rand(-45, 45)); + } + } + else{ + loop(8){ + CreateScoreItem(POINT_REGULAR, x+rand(-75, 75), y+rand(-45, 45)); + } + } + +} + +function SpellItemDrop(scene, x, y){ + + if(ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SHOOTDOWN_COUNT) == 0 && ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SPELL_COUNT) == 0){ + loop(20){ + CreateScoreItem(POINT_BHESTIE, x+rand(-75, 75), y+rand(-45, 45)); + } + loop(10){ + CreateScoreItem(POINT_REGULAR, x+rand(-75, 75), y+rand(-45, 45)); + } + } + else if(ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SHOOTDOWN_COUNT) == 0 && ObjEnemyBossScene_GetInfo(scene, INFO_PLAYER_SPELL_COUNT) >> 0){ + loop(12){ + CreateScoreItem(POINT_REGULAR, x+rand(-75, 75), y+rand(-45, 45)); + } + } + else{} + +} diff --git a/script/KevinSystem/kevin_system/Kevin_Pause.txt b/script/KevinSystem/kevin_system/Kevin_Pause.txt new file mode 100644 index 0000000..efeb9cd --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_Pause.txt @@ -0,0 +1,307 @@ +//一時停止中スクリプト +//#include "./../../script/soundtask.txt" +#include "script/KevinSystem/GeneralSoundLib.txt" + +int STGWIDTH = GetStgFrameWidth(); +int STGHEIGHT = GetStgFrameHeight(); + +@Initialize +{ + _SoundTask(); + PauseGameSFX; + SetAutoDeleteObject(true); + //TBackground(); + TBackgroundNew(0, 0); + TMenu(); + TFunFact(); + //_SoundTask; +} + +@MainLoop +{ + yield; +} + +@Finalize +{ +} + +task TFunFact(){ + + //int y = 0; + + let textchoices = [ + + ["There's no Marisa.[r]She's busy exploding somewhere else.", + "Touhou.", + "Narumi actually doesn't know how to ski.", + "Thanks for playing this game!", + "You can set the amount of starting lives you have in the configurations menu."], + + ["太陽は実際に暑いエッグタルト、ね?", + "東方.", + "このゲームの開発元の一番好きなキャラクターは『僕のヒーローアカデミア』の『口田甲司』ですよ![r]口田くんはすごいとかわいいね...", + "このゲームを遊ぶをありがとうございました!", + "あなたは『OPTIONS』のメニューにはライフカウンターを変化することができます。"], + + ]; + + int x = prand_int(0, length(textchoices[GetCommonData("Language", 0)])-1); + //y = length(textchoices); + + let objText = ObjText_Create(); + ObjText_SetText(objText, textchoices[GetCommonData("Language", 0)][x]); + ObjText_SetFontSize(objText, [30, 32][GetCommonData("Language", 0)]); + ObjText_SetFontType(objText, "コーポレート・ロゴ(ラウンド) ver2 Bold"); + + //ObjText_SetMaxWidth(objText, GetScreenWidth/2); + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER); + + ObjText_SetFontBold(objText, true); + ObjText_SetFontColorTop(objText, 255, 255, 255); + ObjText_SetFontColorBottom(objText, 255, 255, 255); + ObjText_SetFontBorderType(objText, BORDER_FULL); + ObjText_SetFontBorderColor(objText, 0x7D39D9); + ObjText_SetFontBorderWidth(objText, 2); + Obj_SetRenderPriorityI(objText, 10); + ObjRender_SetX(objText, GetScreenWidth/2); + ObjRender_SetY(objText, 7.5*STGHEIGHT/9); + +} + +// renderX and renderY will be TOP-LEFT COORDS +task TBackgroundNew(float renderX, renderY){ + + let obj = ObjPrim_Create(OBJ_SPRITE_2D); + Obj_SetRenderPriorityI(obj, 1); + + let currentFrameTexture = GetTransitionRenderTargetName(); + + ObjPrim_SetTexture(obj, currentFrameTexture); + ObjSprite2D_SetSourceRect(obj, 0, 0, GetScreenWidth(), GetScreenHeight()); + ObjSprite2D_SetDestRect(obj, 0, 0, GetScreenWidth(), GetScreenHeight()); + + ObjRender_SetColor(obj, 0x593DA3); + +} + +task TBackground +{ + task TVertex(var index, var left, var top, var right, var bottom) + { + ObjPrim_SetVertexPosition(obj, index + 0, left, top, 0); + ObjPrim_SetVertexPosition(obj, index + 1, left, bottom, 0); + ObjPrim_SetVertexPosition(obj, index + 2, right, top, 0); + ObjPrim_SetVertexPosition(obj, index + 3, right, top, 0); + ObjPrim_SetVertexPosition(obj, index + 4, left, bottom, 0); + ObjPrim_SetVertexPosition(obj, index + 5, right, bottom, 0); + + ObjPrim_SetVertexUVT(obj, index + 0, left, top); + ObjPrim_SetVertexUVT(obj, index + 1, left, bottom); + ObjPrim_SetVertexUVT(obj, index + 2, right, top); + ObjPrim_SetVertexUVT(obj, index + 3, right, top); + ObjPrim_SetVertexUVT(obj, index + 4, left, bottom); + ObjPrim_SetVertexUVT(obj, index + 5, right, bottom); + + //STGシーン内のみアニメーション + if(left >= 341 && right <= 937 && top >= 45 && bottom <= 677) + { + let alpha = 255; + while(alpha >= 128) + { + ObjPrim_SetVertexAlpha(obj, index + 0, alpha); + ObjPrim_SetVertexAlpha(obj, index + 1, alpha/2); + ObjPrim_SetVertexAlpha(obj, index + 2, alpha/2); + ObjPrim_SetVertexAlpha(obj, index + 3, alpha/2); + ObjPrim_SetVertexAlpha(obj, index + 4, alpha/2); + ObjPrim_SetVertexAlpha(obj, index + 5, alpha); + alpha -= 255 / frame; + + yield; + } + } + } + + //分割設定 + let frame = 30; + let countH = 20; //分割数 + let countV = 30; + let width = 1280 / countH; + let height = 720 / countV; + let target = GetTransitionRenderTargetName(); + let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D); //2D頂点ブジェクト生成 + ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLELIST); + ObjPrim_SetVertexCount(obj, countH * countV * 6); + Obj_SetRenderPriorityI(obj, 0); //描画優先度を設定 + ObjPrim_SetTexture(obj, target); //テクスチャを設定 + + ascent(ix in 0.. countH) + { + ascent(iy in 0.. countV) + { + let index = (ix + iy * countH) * 6; + let left = ix * width; + let right = left + width; + let top = iy * height; + let bottom = top + height; + TVertex(index, left, top, right, bottom); + } + } + +} + +task TMenu +{ + let selectIndex = 0;//選択位置 + function TMenuItem(let index, let mx, let my, let text) + { + function CreateTextObject(let mx, let my, let text) + { + let obj = ObjText_Create(); + ObjText_SetText(obj, text); + ObjText_SetFontSize(obj, 50); + ObjText_SetFontType(obj, "GravityRegular5"); + ObjText_SetFontBold(obj, true); + ObjText_SetHorizontalAlignment(obj, ALIGNMENT_CENTER); + //ObjText_SetMaxWidth(obj, STGWIDTH); + ObjText_SetFontColorTop(obj, 155, 45, 175); + ObjText_SetFontColorBottom(obj, 200, 80, 255); + ObjText_SetFontBorderType(obj, BORDER_FULL); + ObjText_SetFontBorderColor(obj, 255, 255, 255); + ObjText_SetFontBorderWidth(obj, 3.5); + Obj_SetRenderPriorityI(obj, 10); + ObjRender_SetX(obj, mx); + ObjRender_SetY(obj, my); + return obj; + } + + let objText = CreateTextObject(mx, my, text); + let objSelect = CreateTextObject(mx, my, text); + ObjRender_SetBlendType(objSelect, BLEND_ADD_RGB); + + async{ + loop + { + Obj_SetVisible(objSelect, index == selectIndex); + yield; + } + } + + return objText; + } + + //メニュー配置 + + let textchoices = ["Game Paused", "Too Much Snow."]; + int x = prand_int(0, length(textchoices)-1); + let objText = ObjText_Create(); + ObjText_SetText(objText, textchoices[x]); + ObjText_SetFontSize(objText, 72); + ObjText_SetFontType(objText, "GravityBold8"); + + //ObjText_SetMaxWidth(objText, STGWIDTH); + ObjText_SetHorizontalAlignment(objText, ALIGNMENT_CENTER); + + ObjText_SetFontBold(objText, true); + ObjText_SetFontColorTop(objText, 75, 255, 255); + ObjText_SetFontColorBottom(objText, 180, 255, 255); + ObjText_SetFontBorderType(objText, BORDER_FULL); + ObjText_SetFontBorderColor(objText,0, 0, 0); + ObjText_SetFontBorderWidth(objText, 3); + Obj_SetRenderPriorityI(objText, 10); + ObjRender_SetX(objText, GetScreenWidth/2); + ObjRender_SetY(objText, 75); + + let mx = GetScreenWidth/2; + let my = GetScreenHeight/3; + let texts = ["RESUME", "TITLE", "RESTART"]; + var countMenu = length(texts); + ascent(var iText in 0 .. countMenu) + { + int text = TMenuItem(iText, mx, my, texts[iText]); + my += 75; + } + + //キー状態がリセットされるまで待機 + while(GetVirtualKeyState(VK_PAUSE) != KEY_FREE){yield;} + + //メニュー選択処理 + let frameKeyHold = 0;//キー押しっぱなしフレーム数 + //PauseGameSFX; + loop + { + //決定 + if(GetVirtualKeyState(VK_OK) == KEY_PULL) + { + let listResult = [RESULT_CANCEL, RESULT_END, RESULT_RETRY]; + SetScriptResult(listResult[selectIndex]); + CloseScript(GetOwnScriptID()); + return; + } + + //キャンセル + if(GetVirtualKeyState(VK_CANCEL) == KEY_PULL || GetVirtualKeyState(VK_PAUSE) == KEY_PULL) + { + SetScriptResult(RESULT_CANCEL); + CloseScript(GetOwnScriptID()); + return; + } + + //カーソル移動 + if(GetVirtualKeyState(VK_UP) == KEY_PUSH) + { + SelectOptionSFX; + selectIndex--; + } + else if(GetVirtualKeyState(VK_DOWN) == KEY_PUSH) + { + SelectOptionSFX; + selectIndex++; + } + else if(GetVirtualKeyState(VK_UP) == KEY_HOLD) + { + frameKeyHold++; + if(frameKeyHold == 30 || (frameKeyHold > 30 && (frameKeyHold % 10 == 0))) + { + SelectOptionSFX; + selectIndex--; + } + } + else if(GetVirtualKeyState(VK_DOWN) == KEY_HOLD) + { + frameKeyHold++; + if(frameKeyHold == 30 || (frameKeyHold > 30 && (frameKeyHold % 10 == 0))) + { + SelectOptionSFX; + selectIndex++; + } + } + else + { + frameKeyHold = 0; + } + + if(selectIndex < 0) + { + selectIndex = countMenu - 1; + } + else + { + selectIndex %= countMenu; + } + if(GetKeyState(KEY_R) == KEY_PUSH){ + SetScriptResult(RESULT_RETRY); + CloseScript(GetOwnScriptID()); + return; + } + if(GetKeyState(KEY_Q) == KEY_PUSH){ + SetScriptResult(RESULT_END); + CloseScript(GetOwnScriptID()); + return; + } + yield; + } +} + + + diff --git a/script/KevinSystem/kevin_system/Kevin_ReplaySave.txt b/script/KevinSystem/kevin_system/Kevin_ReplaySave.txt new file mode 100644 index 0000000..27949f1 --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_ReplaySave.txt @@ -0,0 +1,437 @@ +//リプレイ保存スクリプト + +int STGWIDTH = GetStgFrameWidth(); +int STGHEIGHT = GetStgFrameHeight(); + +@Initialize +{ + SetAutoDeleteObject(true); + LoadReplayList(); + + TBackgroundNew(0, 0); + TReplayIndexSelection(); +} + +@MainLoop +{ + yield; +} + +@Finalize +{ +} + +let MENU_INDEX_SELECTION = 1; +let MENU_NAME_ENTRY = 2; +let menuMode = MENU_INDEX_SELECTION; + +function DigitToCommaArray(num){ //Natashinitai + + let srcStr = IntToString(num); + let res = []; + let nChar = 0; + for(let i = length(srcStr) - 1; i >= 0; i--){ + res = [srcStr[i]] ~ res; + nChar++; + if(nChar % 3 == 0 && i > 0) res = "," ~ res; + } + return res; + +} + +function CreateTextObject(let mx, let my, float size, let text) +{ + let obj = ObjText_Create(); + ObjText_SetText(obj, text); + ObjText_SetFontSize(obj, size); + ObjText_SetFontType(obj, "Unispace"); + ObjText_SetFontBold(obj, true); + ObjText_SetHorizontalAlignment(obj, ALIGNMENT_LEFT); + //ObjText_SetMaxWidth(obj, STGWIDTH); + ObjText_SetFontColorTop(obj, 155, 45, 175); + ObjText_SetFontColorBottom(obj, 200, 80, 255); + ObjText_SetFontBorderType(obj, BORDER_FULL); + ObjText_SetFontBorderColor(obj, 255, 255, 255); + ObjText_SetFontBorderWidth(obj, 3); + Obj_SetRenderPriorityI(obj, 10); + ObjRender_SetX(obj, mx); + ObjRender_SetY(obj, my); + return obj; +} + +// renderX and renderY will be TOP-LEFT COORDS +task TBackgroundNew(float renderX, renderY){ + + let obj = ObjPrim_Create(OBJ_SPRITE_2D); + Obj_SetRenderPriorityI(obj, 1); + + let currentFrameTexture = GetTransitionRenderTargetName(); + + ObjPrim_SetTexture(obj, currentFrameTexture); + ObjSprite2D_SetSourceRect(obj, 0, 0, GetScreenWidth(), GetScreenHeight()); + ObjSprite2D_SetDestRect(obj, 0, 0, GetScreenWidth(), GetScreenHeight()); + + ObjRender_SetColor(obj, 0x593DA3); + +} + +task TReplayIndexSelection() +{ + let cursorY = 0; + let page = 0; + let countMaxItem = REPLAY_INDEX_DIGIT_MAX - REPLAY_INDEX_DIGIT_MIN + 1; + let countItemPerPage = 10; + let pageMax = trunc((countMaxItem - 1) / countItemPerPage); + pageMax = max(pageMax, 1); + let lastPageMaxCursorY = trunc(countMaxItem / countItemPerPage); + + task TMenuItem(let itemY) + { + let objText = CreateTextObject(90, 45 + 35 * itemY, 28, ""); + let objSelect = CreateTextObject(90, 45 + 35 * itemY, 28, ""); + ObjRender_SetAlpha(objText, 125); + ObjRender_SetAlpha(objSelect, 80); + ObjRender_SetBlendType(objSelect, BLEND_ADD_ARGB); + + let oldPage = -1; + while(menuMode == MENU_INDEX_SELECTION) + { + if(page != oldPage) + { + let index = page * countItemPerPage + itemY + 1; + let text = rtos("00", index) ~ " "; + if(IsValidReplayIndex(index)) + { + text = text ~ vtos("-8s", GetReplayInfo(index, REPLAY_USER_NAME)) ~ " "; + text = text ~ GetReplayInfo(index, REPLAY_DATE_TIME) ~ " "; + text = text ~ DigitToCommaArray(trunc(GetReplayInfo(index, REPLAY_TOTAL_SCORE)/10)*10) ~ " "; + text = text ~ GetReplayInfo(index, REPLAY_PLAYER_NAME) ~ " "; + text = text ~ GetReplayUserData(index, "Difficulty"); + + /* + SetReplayUserData("Starting Lives", GetCommonData("Starting Lives Selected", 5)); + SetReplayUserData("Player", GetReplayInfo(index, REPLAY_PLAYER_NAME)); + SetReplayUserData("Difficulty", GetCommonData("Difficulty", "Hard")); + */ + + } + else + { + text = text ~ "Entry Blank"; + } + ObjText_SetText(objText, text); + ObjText_SetText(objSelect, text); + oldPage = page; + } + + if(page == pageMax && itemY >= lastPageMaxCursorY) + { + Obj_SetVisible(objText, false); + Obj_SetVisible(objSelect, false); + } + else + { + Obj_SetVisible(objText, true); + Obj_SetVisible(objSelect, itemY == cursorY); + } + + yield; + } + Obj_Delete(objText); + Obj_Delete(objSelect); + } + + ascent(let iItem in 0 .. countItemPerPage) + { + TMenuItem(iItem); + } + + //キー状態がリセットされるまで待機 + while(GetVirtualKeyState(VK_OK) != KEY_FREE){yield;} + + //キー処理 + let frameKeyHold = 0;//キー押しっぱなしフレーム数 + while(menuMode == MENU_INDEX_SELECTION) + { + //決定 + if(GetVirtualKeyState(VK_OK) == KEY_PULL) + { + menuMode = MENU_NAME_ENTRY; + let index = page * countItemPerPage + cursorY + 1; + TNameEntry(index); + + break; + } + + if(GetVirtualKeyState(VK_CANCEL) == KEY_PUSH){ + SetScriptResult(RESULT_END); + CloseScript(GetOwnScriptID()); + } + + //カーソル移動 + if(GetVirtualKeyState(VK_UP) == KEY_PUSH || GetVirtualKeyState(VK_UP) == KEY_HOLD) + { + frameKeyHold++; + if(GetVirtualKeyState(VK_UP) == KEY_PUSH || + frameKeyHold == 20 || + (frameKeyHold > 20 && (frameKeyHold % 10 == 0))) + { + cursorY--; + } + } + else if(GetVirtualKeyState(VK_DOWN) == KEY_PUSH || GetVirtualKeyState(VK_DOWN) == KEY_HOLD) + { + frameKeyHold++; + if(GetVirtualKeyState(VK_DOWN) == KEY_PUSH || + frameKeyHold == 20 || + (frameKeyHold > 20 && (frameKeyHold % 10 == 0))) + { + cursorY++; + } + } + else if(GetVirtualKeyState(VK_LEFT) == KEY_PUSH || GetVirtualKeyState(VK_LEFT) == KEY_HOLD) + { + frameKeyHold++; + if(GetVirtualKeyState(VK_LEFT) == KEY_PUSH || + frameKeyHold == 20 || + (frameKeyHold > 20 && (frameKeyHold % 10 == 0))) + { + page--; + } + } + else if(GetVirtualKeyState(VK_RIGHT) == KEY_PUSH || GetVirtualKeyState(VK_RIGHT) == KEY_HOLD) + { + frameKeyHold++; + if(GetVirtualKeyState(VK_RIGHT) == KEY_PUSH || + frameKeyHold == 20 || + (frameKeyHold > 20 && (frameKeyHold % 10 == 0))) + { + page++; + } + } + else + { + frameKeyHold = 0; + } + + if(page < 0) + { + page = pageMax; + } + else if(page > pageMax) + { + page = 0; + } + + if(page != pageMax) + { + if(cursorY < 0) + { + cursorY = countItemPerPage - 1; + } + else if(cursorY >= countItemPerPage) + { + cursorY = 0; + } + } + else + { + if(cursorY < 0) + { + cursorY = lastPageMaxCursorY - 1; + } + else if(cursorY >= lastPageMaxCursorY) + { + cursorY = 0; + } + } + + yield; + } + +} + + +task TNameEntry(let replayIndex) +{ + let strTextIn = + [ + ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"], + ["Q","R","S","T","U","V","W","X","Y","Z",".",",",":",";","_","@"], + ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p"], + ["q","r","s","t","u","v","w","x","y","z","+","-","/","*","=","%"], + ["0","1","2","3","4","5","6","7","8","9","0","!","?","'","\"","$"], + ["(",")","{","}","[","]","<",">","&","#","|","~","^"," "," ","終"] + ]; + + let strTextView = + [ + ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P"], + ["Q","R","S","T","U","V","W","X","Y","Z",".",",",":",";","_","@"], + ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p"], + ["q","r","s","t","u","v","w","x","y","z","+","-","/","*","=","%"], + ["0","1","2","3","4","5","6","7","8","9","0","!","?","'","\"","$"], + ["(",")","{","}","&osb;","&csb;","<",">","&","#","|","~","^"," "," ","»"] + ]; + + let cursorX = 0; + let cursorY = 0; + let maxCursorX = length(strTextIn[0]); + let maxCursorY = length(strTextIn); + + task TMenuItem(let itemX, let itemY) + { + let objText = CreateTextObject(GetStgFrameWidth()/4 + itemX * 42, 400 + itemY * 42, 40, strTextView[itemY][itemX]); + let objSelect = CreateTextObject(GetStgFrameWidth()/4+ itemX * 42, 400 + itemY * 42, 40, strTextView[itemY][itemX]); + ObjRender_SetBlendType(objSelect, BLEND_ADD_ARGB); + + while(menuMode == MENU_NAME_ENTRY) + { + Obj_SetVisible(objSelect, itemX == cursorX && itemY == cursorY); + yield; + } + Obj_Delete(objText); + Obj_Delete(objSelect); + } + + ascent(let iY in 0..maxCursorY) + { + ascent(let iX in 0 .. maxCursorX) + { + TMenuItem(iX, iY); + } + } + + //キー状態がリセットされるまで待機 + while(GetVirtualKeyState(VK_OK) != KEY_FREE){yield;} + + //入力済み文字 + let userName = ""; + let objName = CreateTextObject(GetStgFrameWidth()/4, 200, 45, ""); + task TNameCursor() + { + let objCursor = CreateTextObject(GetStgFrameWidth()/4, 200, 45, "_"); + while(menuMode == MENU_NAME_ENTRY) + { + let nameLength = length(userName); + ObjRender_SetX(objCursor, GetStgFrameWidth()/4 + nameLength * 30); + Obj_SetVisible(objCursor, nameLength < 8); + yield; + } + Obj_Delete(objCursor); + } + TNameCursor; + + //キー処理 + let frameKeyHold = 0;//キー押しっぱなしフレーム数 + while(menuMode == MENU_NAME_ENTRY) + { + + if(GetVirtualKeyState(VK_OK) == KEY_PULL) + { + //決定 + let nameLength = length(userName); + if(cursorX == maxCursorX-1 && cursorY == maxCursorY-1) + { + //終了キー + if(nameLength == 0) + { + userName = "Gay"; + } + else + { + SetReplayUserData("Starting Lives", GetCommonData("Starting Lives Selected", 5)); + SetReplayUserData("Player Team", GetCommonData("Player Team", "ByakMiko")); + SetReplayUserData("Difficulty", GetCommonData("Difficulty", "Standard")); + SetReplayUserData("Dialogue Skip", GetCommonData("Dialogue Skip Mode", 0)); + SaveReplay(replayIndex, userName); + SetScriptResult(RESULT_END); + CloseScript(GetOwnScriptID()); + return; + } + } + else if(nameLength < 8) + { + userName = userName ~ strTextIn[cursorY][cursorX]; + } + } + if(GetVirtualKeyState(VK_CANCEL) == KEY_PULL) + { + //キャンセル + let nameLength = length(userName); + if(nameLength > 0) + { + userName = userName[0..nameLength-1]; + } + else{menuMode = MENU_INDEX_SELECTION; TReplayIndexSelection(); break;} + } + ObjText_SetText(objName, userName); + + //カーソル移動 + if(GetVirtualKeyState(VK_UP) == KEY_PUSH || GetVirtualKeyState(VK_UP) == KEY_HOLD) + { + frameKeyHold++; + if(GetVirtualKeyState(VK_UP) == KEY_PUSH || + frameKeyHold == 20 || + (frameKeyHold > 20 && (frameKeyHold % 10 == 0))) + { + cursorY--; + } + } + else if(GetVirtualKeyState(VK_DOWN) == KEY_PUSH || GetVirtualKeyState(VK_DOWN) == KEY_HOLD) + { + frameKeyHold++; + if(GetVirtualKeyState(VK_DOWN) == KEY_PUSH || + frameKeyHold == 20 || + (frameKeyHold > 20 && (frameKeyHold % 10 == 0))) + { + cursorY++; + } + } + else if(GetVirtualKeyState(VK_LEFT) == KEY_PUSH || GetVirtualKeyState(VK_LEFT) == KEY_HOLD) + { + frameKeyHold++; + if(GetVirtualKeyState(VK_LEFT) == KEY_PUSH || + frameKeyHold == 20 || + (frameKeyHold > 20 && (frameKeyHold % 10 == 0))) + { + cursorX--; + } + } + else if(GetVirtualKeyState(VK_RIGHT) == KEY_PUSH || GetVirtualKeyState(VK_RIGHT) == KEY_HOLD) + { + frameKeyHold++; + if(GetVirtualKeyState(VK_RIGHT) == KEY_PUSH || + frameKeyHold == 20 || + (frameKeyHold > 20 && (frameKeyHold % 10 == 0))) + { + cursorX++; + } + } + else + { + frameKeyHold = 0; + } + + if(cursorX < 0) + { + cursorX = maxCursorX-1; + } + else if(cursorX >= maxCursorX) + { + cursorX = 0; + } + + if(cursorY < 0) + { + cursorY = maxCursorY-1; + } + else if(cursorY >= maxCursorY) + { + cursorY = 0; + } + + yield; + } +} + diff --git a/script/KevinSystem/kevin_system/Lib_Const.dnh b/script/KevinSystem/kevin_system/Lib_Const.dnh new file mode 100644 index 0000000..06c7874 --- /dev/null +++ b/script/KevinSystem/kevin_system/Lib_Const.dnh @@ -0,0 +1,80 @@ +//Custom events + +const EV_START_MUSIC = EV_USER + 411i; +const EV_BOSS_MUSIC = EV_USER + 412i; + +const EV_DROP_POINT_ENEMY = EV_USER + 200i; +const EV_DROP_PIV_ENEMY = EV_USER + 201i; +const EV_SINGLE_ITEM_DROP = EV_USER + 202i; +const EV_DROP_EXTEND = EV_USER + 203i; +const EV_DROP_AMMO_ENEMY = EV_USER + 204i; + +const EV_EXPLODE = EV_USER + 300i; + +// Chain events + +const EV_CHAIN_MAX = EV_USER + 301i; // Play sound effect when chain is max +const EV_CHAIN_RELEASE = EV_USER + 302i; // Make enemies drop golden point items when chain is cashed in +const EV_CHAIN_END = EV_USER + 303i; // End/reset chain when gauge goes to 0 +const CHAIN_MAX = 64; + +// Card shop events + +const EV_SHOP_CALL = EV_USER + 400i; // Call shop (in stage) +const EV_SHOP_OPEN = EV_USER + 401i; // Request to open shop (in player script) when CALL is notified +const EV_SHOP_GAIN = EV_USER + 402i; // Shop is opened in package. Afterwards, add ability via notifying this event (in player script) + +// Convenience constants + +const STG_WIDTH = GetStgFrameWidth(); +const STG_HEIGHT = GetStgFrameHeight(); + +// Card names + +const CARD_NAMES = +[ + // Shop 1 + + "Hitchcock Birds", + "Turtle Cannon", + "Phoenix Feather", + "Devil's Crown", + + // Shop 2 + + "Irresistible Demand", + "Danmaku Catcher", + "Mango Jam", + "Cucumber Jam", + + // Shop 3 + + "K*taka Fried Chicken", + "Magic Absorber", + "Warrior's Breastplate", + "20/20 Goggles", + + // Shop 4 + + "Fossil Spear", + "Oni's Cursed Gourd", + "Bee-Powered Laser", + "Radiant Warrior", + + // Final Shop + + "Blacksmith's Offer", + "Potionmaker's Mist", + "Marketeer's Rainbow" + +]; + +// Misc + +const EFFECTCUT_PTR = LoadAreaCommonDataValuePointer("Config", "EffectCut", 0); + +const ITEMID_PTR = LoadAreaCommonDataValuePointer("ScriptID", "ItemID", 0); +const SYSTEMID_PTR = LoadAreaCommonDataValuePointer("ScriptID", "SystemID", 0); + +const FLYINGENM_PTR = LoadCommonDataValuePointer("Flying Defeated", 0); +const GROUNDENM_PTR = LoadCommonDataValuePointer("Ground Defeated", 0); \ No newline at end of file diff --git a/script/KevinSystem/kevin_system/ValueLib.txt b/script/KevinSystem/kevin_system/ValueLib.txt new file mode 100644 index 0000000..e69de29 diff --git a/script/KevinSystem/se/e/seGetSpellCardBonus.wav b/script/KevinSystem/se/e/seGetSpellCardBonus.wav new file mode 100644 index 0000000..dec1071 Binary files /dev/null and b/script/KevinSystem/se/e/seGetSpellCardBonus.wav differ diff --git a/script/KevinSystem/se/e/seUseSpellCard.wav b/script/KevinSystem/se/e/seUseSpellCard.wav new file mode 100644 index 0000000..bab7a69 Binary files /dev/null and b/script/KevinSystem/se/e/seUseSpellCard.wav differ diff --git a/script/Package_FuncLib.dnh b/script/Package_FuncLib.dnh new file mode 100644 index 0000000..f81a6ae Binary files /dev/null and b/script/Package_FuncLib.dnh differ diff --git a/script/Package_MenuLib.dnh b/script/Package_MenuLib.dnh new file mode 100644 index 0000000..bf343d8 Binary files /dev/null and b/script/Package_MenuLib.dnh differ diff --git a/script/default_system/Default_Background_IceMountain.txt b/script/default_system/Default_Background_IceMountain.txt new file mode 100644 index 0000000..96074eb Binary files /dev/null and b/script/default_system/Default_Background_IceMountain.txt differ diff --git a/script/default_system/Default_Effect.txt b/script/default_system/Default_Effect.txt new file mode 100644 index 0000000..8645b1f Binary files /dev/null and b/script/default_system/Default_Effect.txt differ diff --git a/script/default_system/Default_EndScene.txt b/script/default_system/Default_EndScene.txt new file mode 100644 index 0000000..1656d86 Binary files /dev/null and b/script/default_system/Default_EndScene.txt differ diff --git a/script/default_system/Default_Pause.txt b/script/default_system/Default_Pause.txt new file mode 100644 index 0000000..38222f6 Binary files /dev/null and b/script/default_system/Default_Pause.txt differ diff --git a/script/default_system/Default_ReplaySaveScene.txt b/script/default_system/Default_ReplaySaveScene.txt new file mode 100644 index 0000000..73a97ec Binary files /dev/null and b/script/default_system/Default_ReplaySaveScene.txt differ diff --git a/script/default_system/Default_ShotConst.txt b/script/default_system/Default_ShotConst.txt new file mode 100644 index 0000000..00b50a9 Binary files /dev/null and b/script/default_system/Default_ShotConst.txt differ diff --git a/script/default_system/Default_ShotData.txt b/script/default_system/Default_ShotData.txt new file mode 100644 index 0000000..ac117e2 Binary files /dev/null and b/script/default_system/Default_ShotData.txt differ diff --git a/script/default_system/Default_System.txt b/script/default_system/Default_System.txt new file mode 100644 index 0000000..74124d8 Binary files /dev/null and b/script/default_system/Default_System.txt differ diff --git a/script/default_system/Default_System_MagicCircle.txt b/script/default_system/Default_System_MagicCircle.txt new file mode 100644 index 0000000..ceec98d Binary files /dev/null and b/script/default_system/Default_System_MagicCircle.txt differ diff --git a/script/default_system/img/Default_Background_IceMountain.bmp b/script/default_system/img/Default_Background_IceMountain.bmp new file mode 100644 index 0000000..61db0b6 Binary files /dev/null and b/script/default_system/img/Default_Background_IceMountain.bmp differ diff --git a/script/default_system/img/Default_Background_IceMountain.mqo b/script/default_system/img/Default_Background_IceMountain.mqo new file mode 100644 index 0000000..f2388aa --- /dev/null +++ b/script/default_system/img/Default_Background_IceMountain.mqo @@ -0,0 +1,249 @@ +Metasequoia Document +Format Text Ver 1.0 + +Scene { + pos -30.1096 -34.3943 789.2167 + lookat 0.0000 0.0000 0.0000 + head -1.8300 + pich 0.5300 + ortho 0 + zoom2 2.0091 + amb 0.250 0.250 0.250 +} +Material 1 { + "mat0" shader(3) col(1.000 1.000 1.000 1.000) dif(1.000) amb(0.600) emi(0.000) spc(0.000) power(1.00) tex("Default_Background_IceMountain.bmp") +} +Object "obj0" { + visible 15 + locking 0 + shading 1 + facet 59.5 + color 0.898 0.498 0.698 + color_type 0 + vertex 121 { + 500.0000 0.0000 500.0000 + 400.0000 0.0000 500.0000 + 400.0000 0.0000 400.0000 + 500.0000 0.0000 400.0000 + 300.0000 0.0000 500.0000 + 300.0000 0.0000 400.0000 + 200.0000 0.0000 500.0000 + 200.0000 0.0000 400.0000 + 100.0000 0.0000 500.0000 + 100.0000 0.0000 400.0000 + 0.0000 0.0000 500.0000 + 0.0000 0.0000 400.0000 + -100.0000 0.0000 500.0000 + -100.0000 0.0000 400.0000 + -200.0000 0.0000 500.0000 + -200.0000 0.0000 400.0000 + -300.0000 0.0000 500.0000 + -300.0000 0.0000 400.0000 + -400.0000 0.0000 500.0000 + -400.0000 0.0000 400.0000 + -500.0000 0.0000 500.0000 + -500.0000 0.0000 400.0000 + 400.0000 0.0000 300.0000 + 500.0000 0.0000 300.0000 + 300.0000 0.0000 300.0000 + 181.9993 25.4220 251.4612 + 87.5351 67.6823 172.7408 + 44.9009 66.8717 169.9153 + -84.3673 81.3440 243.9148 + -165.8140 45.4173 301.9575 + -265.8140 45.4173 301.9575 + -400.0000 0.0000 300.0000 + -500.0000 0.0000 300.0000 + 400.0000 0.0000 200.0000 + 500.0000 0.0000 200.0000 + 298.8597 14.8172 185.7207 + 126.2485 97.3682 134.2916 + 23.1660 119.7628 65.2812 + -48.3018 103.9974 84.5904 + -78.9084 75.3832 146.5701 + -165.8140 45.4173 201.9575 + -265.8140 45.4173 201.9575 + -400.0000 0.0000 200.0000 + -500.0000 0.0000 200.0000 + 400.0000 0.0000 100.0000 + 500.0000 0.0000 100.0000 + 255.6389 58.0200 114.1542 + 142.7559 56.0312 43.6297 + 36.2995 41.0596 -5.4791 + -62.4664 75.8076 -4.6157 + -140.5926 75.4124 49.9508 + -231.5631 8.7596 76.5071 + -300.0000 0.0000 100.0000 + -400.0000 0.0000 100.0000 + -500.0000 0.0000 100.0000 + 400.0000 0.0000 0.0000 + 500.0000 0.0000 0.0000 + 221.8938 66.4581 1.9473 + 143.8961 41.2140 -42.0910 + 15.1947 34.4286 -102.5772 + -71.9221 36.4174 -32.0527 + -158.7284 63.2710 -47.6829 + -211.9965 33.8983 -68.7922 + -280.4333 25.1387 -45.2993 + -400.0000 0.0000 0.0000 + -500.0000 0.0000 0.0000 + 400.0000 0.0000 -100.0000 + 500.0000 0.0000 -100.0000 + 300.0000 0.0000 -100.0000 + 200.0000 0.0000 -100.0000 + 28.0779 36.4174 -132.0527 + -71.9221 36.4174 -132.0527 + -109.7092 10.8928 -120.7280 + -174.9080 20.0401 -134.2268 + -274.9080 20.0401 -134.2268 + -400.0000 0.0000 -100.0000 + -500.0000 0.0000 -100.0000 + 400.0000 0.0000 -200.0000 + 500.0000 0.0000 -200.0000 + 258.7267 31.4519 -195.8992 + 154.2999 93.4632 -171.4050 + 83.7472 49.4622 -230.7452 + -16.2528 49.4622 -230.7452 + -139.3118 37.0325 -183.7692 + -214.2198 57.0726 -217.9960 + -274.9080 20.0401 -234.2268 + -400.0000 0.0000 -200.0000 + -500.0000 0.0000 -200.0000 + 400.0000 0.0000 -300.0000 + 500.0000 0.0000 -300.0000 + 287.1706 10.4937 -295.7311 + 187.1706 10.4937 -295.7311 + 125.2088 40.5356 -370.5968 + 25.2089 40.5356 -370.5968 + -139.3118 37.0325 -283.7693 + -239.3118 37.0325 -283.7693 + -300.0000 0.0000 -300.0000 + -400.0000 0.0000 -300.0000 + -500.0000 0.0000 -300.0000 + 400.0000 0.0000 -400.0000 + 500.0000 0.0000 -400.0000 + 300.0000 0.0000 -400.0000 + 200.0000 0.0000 -400.0000 + 100.0000 0.0000 -400.0000 + 0.0000 0.0000 -400.0000 + -100.0000 0.0000 -400.0000 + -200.0000 0.0000 -400.0000 + -300.0000 0.0000 -400.0000 + -400.0000 0.0000 -400.0000 + -500.0000 0.0000 -400.0000 + 400.0000 0.0000 -500.0000 + 500.0000 0.0000 -500.0000 + 300.0000 0.0000 -500.0000 + 200.0000 0.0000 -500.0000 + 100.0000 0.0000 -500.0000 + 0.0000 0.0000 -500.0000 + -100.0000 0.0000 -500.0000 + -200.0000 0.0000 -500.0000 + -300.0000 0.0000 -500.0000 + -400.0000 0.0000 -500.0000 + -500.0000 0.0000 -500.0000 + } + face 100 { + 4 V(0 1 2 3) M(0) UV(0.00000 0.00000 0.10000 0.00000 0.10000 0.10000 0.00000 0.10000) + 4 V(1 4 5 2) M(0) UV(0.10000 0.00000 0.20000 0.00000 0.20000 0.10000 0.10000 0.10000) + 4 V(4 6 7 5) M(0) UV(0.20000 0.00000 0.30000 0.00000 0.30000 0.10000 0.20000 0.10000) + 4 V(6 8 9 7) M(0) UV(0.30000 0.00000 0.40000 0.00000 0.40000 0.10000 0.30000 0.10000) + 4 V(8 10 11 9) M(0) UV(0.40000 0.00000 0.50000 0.00000 0.50000 0.10000 0.40000 0.10000) + 4 V(10 12 13 11) M(0) UV(0.50000 0.00000 0.60000 0.00000 0.60000 0.10000 0.50000 0.10000) + 4 V(12 14 15 13) M(0) UV(0.60000 0.00000 0.70000 0.00000 0.70000 0.10000 0.60000 0.10000) + 4 V(14 16 17 15) M(0) UV(0.70000 0.00000 0.80000 0.00000 0.80000 0.10000 0.70000 0.10000) + 4 V(16 18 19 17) M(0) UV(0.80000 0.00000 0.90000 0.00000 0.90000 0.10000 0.80000 0.10000) + 4 V(18 20 21 19) M(0) UV(0.90000 0.00000 1.00000 0.00000 1.00000 0.10000 0.90000 0.10000) + 4 V(3 2 22 23) M(0) UV(0.00000 0.10000 0.10000 0.10000 0.10000 0.20000 0.00000 0.20000) + 4 V(2 5 24 22) M(0) UV(0.10000 0.10000 0.20000 0.10000 0.20000 0.20000 0.10000 0.20000) + 4 V(5 7 25 24) M(0) UV(0.20000 0.10000 0.30000 0.10000 0.30000 0.20000 0.20000 0.20000) + 4 V(7 9 26 25) M(0) UV(0.30000 0.10000 0.40000 0.10000 0.40000 0.20000 0.30000 0.20000) + 4 V(9 11 27 26) M(0) UV(0.40000 0.10000 0.50000 0.10000 0.50000 0.20000 0.40000 0.20000) + 4 V(11 13 28 27) M(0) UV(0.50000 0.10000 0.60000 0.10000 0.60000 0.20000 0.50000 0.20000) + 4 V(13 15 29 28) M(0) UV(0.60000 0.10000 0.70000 0.10000 0.70000 0.20000 0.60000 0.20000) + 4 V(15 17 30 29) M(0) UV(0.70000 0.10000 0.80000 0.10000 0.80000 0.20000 0.70000 0.20000) + 4 V(17 19 31 30) M(0) UV(0.80000 0.10000 0.90000 0.10000 0.90000 0.20000 0.80000 0.20000) + 4 V(19 21 32 31) M(0) UV(0.90000 0.10000 1.00000 0.10000 1.00000 0.20000 0.90000 0.20000) + 4 V(23 22 33 34) M(0) UV(0.00000 0.20000 0.10000 0.20000 0.10000 0.30000 0.00000 0.30000) + 4 V(22 24 35 33) M(0) UV(0.10000 0.20000 0.20000 0.20000 0.20000 0.30000 0.10000 0.30000) + 4 V(24 25 36 35) M(0) UV(0.20000 0.20000 0.30000 0.20000 0.30000 0.30000 0.20000 0.30000) + 4 V(25 26 37 36) M(0) UV(0.30000 0.20000 0.40000 0.20000 0.40000 0.30000 0.30000 0.30000) + 4 V(26 27 38 37) M(0) UV(0.40000 0.20000 0.50000 0.20000 0.50000 0.30000 0.40000 0.30000) + 4 V(27 28 39 38) M(0) UV(0.50000 0.20000 0.60000 0.20000 0.60000 0.30000 0.50000 0.30000) + 4 V(28 29 40 39) M(0) UV(0.60000 0.20000 0.70000 0.20000 0.70000 0.30000 0.60000 0.30000) + 4 V(29 30 41 40) M(0) UV(0.70000 0.20000 0.80000 0.20000 0.80000 0.30000 0.70000 0.30000) + 4 V(30 31 42 41) M(0) UV(0.80000 0.20000 0.90000 0.20000 0.90000 0.30000 0.80000 0.30000) + 4 V(31 32 43 42) M(0) UV(0.90000 0.20000 1.00000 0.20000 1.00000 0.30000 0.90000 0.30000) + 4 V(34 33 44 45) M(0) UV(0.00000 0.30000 0.10000 0.30000 0.10000 0.40000 0.00000 0.40000) + 4 V(33 35 46 44) M(0) UV(0.10000 0.30000 0.20000 0.30000 0.20000 0.40000 0.10000 0.40000) + 4 V(35 36 47 46) M(0) UV(0.20000 0.30000 0.30000 0.30000 0.30000 0.40000 0.20000 0.40000) + 4 V(36 37 48 47) M(0) UV(0.30000 0.30000 0.40000 0.30000 0.40000 0.40000 0.30000 0.40000) + 4 V(37 38 49 48) M(0) UV(0.40000 0.30000 0.50000 0.30000 0.50000 0.40000 0.40000 0.40000) + 4 V(38 39 50 49) M(0) UV(0.50000 0.30000 0.60000 0.30000 0.60000 0.40000 0.50000 0.40000) + 4 V(39 40 51 50) M(0) UV(0.60000 0.30000 0.70000 0.30000 0.70000 0.40000 0.60000 0.40000) + 4 V(40 41 52 51) M(0) UV(0.70000 0.30000 0.80000 0.30000 0.80000 0.40000 0.70000 0.40000) + 4 V(41 42 53 52) M(0) UV(0.80000 0.30000 0.90000 0.30000 0.90000 0.40000 0.80000 0.40000) + 4 V(42 43 54 53) M(0) UV(0.90000 0.30000 1.00000 0.30000 1.00000 0.40000 0.90000 0.40000) + 4 V(45 44 55 56) M(0) UV(0.00000 0.40000 0.10000 0.40000 0.10000 0.50000 0.00000 0.50000) + 4 V(44 46 57 55) M(0) UV(0.10000 0.40000 0.20000 0.40000 0.20000 0.50000 0.10000 0.50000) + 4 V(46 47 58 57) M(0) UV(0.20000 0.40000 0.30000 0.40000 0.30000 0.50000 0.20000 0.50000) + 4 V(47 48 59 58) M(0) UV(0.30000 0.40000 0.40000 0.40000 0.40000 0.50000 0.30000 0.50000) + 4 V(48 49 60 59) M(0) UV(0.40000 0.40000 0.50000 0.40000 0.50000 0.50000 0.40000 0.50000) + 4 V(49 50 61 60) M(0) UV(0.50000 0.40000 0.60000 0.40000 0.60000 0.50000 0.50000 0.50000) + 4 V(50 51 62 61) M(0) UV(0.60000 0.40000 0.70000 0.40000 0.70000 0.50000 0.60000 0.50000) + 4 V(51 52 63 62) M(0) UV(0.70000 0.40000 0.80000 0.40000 0.80000 0.50000 0.70000 0.50000) + 4 V(52 53 64 63) M(0) UV(0.80000 0.40000 0.90000 0.40000 0.90000 0.50000 0.80000 0.50000) + 4 V(53 54 65 64) M(0) UV(0.90000 0.40000 1.00000 0.40000 1.00000 0.50000 0.90000 0.50000) + 4 V(56 55 66 67) M(0) UV(0.00000 0.50000 0.10000 0.50000 0.10000 0.60000 0.00000 0.60000) + 4 V(55 57 68 66) M(0) UV(0.10000 0.50000 0.20000 0.50000 0.20000 0.60000 0.10000 0.60000) + 4 V(57 58 69 68) M(0) UV(0.20000 0.50000 0.30000 0.50000 0.30000 0.60000 0.20000 0.60000) + 4 V(58 59 70 69) M(0) UV(0.30000 0.50000 0.40000 0.50000 0.40000 0.60000 0.30000 0.60000) + 4 V(59 60 71 70) M(0) UV(0.40000 0.50000 0.50000 0.50000 0.50000 0.60000 0.40000 0.60000) + 4 V(60 61 72 71) M(0) UV(0.50000 0.50000 0.60000 0.50000 0.60000 0.60000 0.50000 0.60000) + 4 V(61 62 73 72) M(0) UV(0.60000 0.50000 0.70000 0.50000 0.70000 0.60000 0.60000 0.60000) + 4 V(62 63 74 73) M(0) UV(0.70000 0.50000 0.80000 0.50000 0.80000 0.60000 0.70000 0.60000) + 4 V(63 64 75 74) M(0) UV(0.80000 0.50000 0.90000 0.50000 0.90000 0.60000 0.80000 0.60000) + 4 V(64 65 76 75) M(0) UV(0.90000 0.50000 1.00000 0.50000 1.00000 0.60000 0.90000 0.60000) + 4 V(67 66 77 78) M(0) UV(0.00000 0.60000 0.10000 0.60000 0.10000 0.70000 0.00000 0.70000) + 4 V(66 68 79 77) M(0) UV(0.10000 0.60000 0.20000 0.60000 0.20000 0.70000 0.10000 0.70000) + 4 V(68 69 80 79) M(0) UV(0.20000 0.60000 0.30000 0.60000 0.30000 0.70000 0.20000 0.70000) + 4 V(69 70 81 80) M(0) UV(0.30000 0.60000 0.40000 0.60000 0.40000 0.70000 0.30000 0.70000) + 4 V(70 71 82 81) M(0) UV(0.40000 0.60000 0.50000 0.60000 0.50000 0.70000 0.40000 0.70000) + 4 V(71 72 83 82) M(0) UV(0.50000 0.60000 0.60000 0.60000 0.60000 0.70000 0.50000 0.70000) + 4 V(72 73 84 83) M(0) UV(0.60000 0.60000 0.70000 0.60000 0.70000 0.70000 0.60000 0.70000) + 4 V(73 74 85 84) M(0) UV(0.70000 0.60000 0.80000 0.60000 0.80000 0.70000 0.70000 0.70000) + 4 V(74 75 86 85) M(0) UV(0.80000 0.60000 0.90000 0.60000 0.90000 0.70000 0.80000 0.70000) + 4 V(75 76 87 86) M(0) UV(0.90000 0.60000 1.00000 0.60000 1.00000 0.70000 0.90000 0.70000) + 4 V(78 77 88 89) M(0) UV(0.00000 0.70000 0.10000 0.70000 0.10000 0.80000 0.00000 0.80000) + 4 V(77 79 90 88) M(0) UV(0.10000 0.70000 0.20000 0.70000 0.20000 0.80000 0.10000 0.80000) + 4 V(79 80 91 90) M(0) UV(0.20000 0.70000 0.30000 0.70000 0.30000 0.80000 0.20000 0.80000) + 4 V(80 81 92 91) M(0) UV(0.30000 0.70000 0.40000 0.70000 0.40000 0.80000 0.30000 0.80000) + 4 V(81 82 93 92) M(0) UV(0.40000 0.70000 0.50000 0.70000 0.50000 0.80000 0.40000 0.80000) + 4 V(82 83 94 93) M(0) UV(0.50000 0.70000 0.60000 0.70000 0.60000 0.80000 0.50000 0.80000) + 4 V(83 84 95 94) M(0) UV(0.60000 0.70000 0.70000 0.70000 0.70000 0.80000 0.60000 0.80000) + 4 V(84 85 96 95) M(0) UV(0.70000 0.70000 0.80000 0.70000 0.80000 0.80000 0.70000 0.80000) + 4 V(85 86 97 96) M(0) UV(0.80000 0.70000 0.90000 0.70000 0.90000 0.80000 0.80000 0.80000) + 4 V(86 87 98 97) M(0) UV(0.90000 0.70000 1.00000 0.70000 1.00000 0.80000 0.90000 0.80000) + 4 V(89 88 99 100) M(0) UV(0.00000 0.80000 0.10000 0.80000 0.10000 0.90000 0.00000 0.90000) + 4 V(88 90 101 99) M(0) UV(0.10000 0.80000 0.20000 0.80000 0.20000 0.90000 0.10000 0.90000) + 4 V(90 91 102 101) M(0) UV(0.20000 0.80000 0.30000 0.80000 0.30000 0.90000 0.20000 0.90000) + 4 V(91 92 103 102) M(0) UV(0.30000 0.80000 0.40000 0.80000 0.40000 0.90000 0.30000 0.90000) + 4 V(92 93 104 103) M(0) UV(0.40000 0.80000 0.50000 0.80000 0.50000 0.90000 0.40000 0.90000) + 4 V(93 94 105 104) M(0) UV(0.50000 0.80000 0.60000 0.80000 0.60000 0.90000 0.50000 0.90000) + 4 V(94 95 106 105) M(0) UV(0.60000 0.80000 0.70000 0.80000 0.70000 0.90000 0.60000 0.90000) + 4 V(95 96 107 106) M(0) UV(0.70000 0.80000 0.80000 0.80000 0.80000 0.90000 0.70000 0.90000) + 4 V(96 97 108 107) M(0) UV(0.80000 0.80000 0.90000 0.80000 0.90000 0.90000 0.80000 0.90000) + 4 V(97 98 109 108) M(0) UV(0.90000 0.80000 1.00000 0.80000 1.00000 0.90000 0.90000 0.90000) + 4 V(100 99 110 111) M(0) UV(0.00000 0.90000 0.10000 0.90000 0.10000 1.00000 0.00000 1.00000) + 4 V(99 101 112 110) M(0) UV(0.10000 0.90000 0.20000 0.90000 0.20000 1.00000 0.10000 1.00000) + 4 V(101 102 113 112) M(0) UV(0.20000 0.90000 0.30000 0.90000 0.30000 1.00000 0.20000 1.00000) + 4 V(102 103 114 113) M(0) UV(0.30000 0.90000 0.40000 0.90000 0.40000 1.00000 0.30000 1.00000) + 4 V(103 104 115 114) M(0) UV(0.40000 0.90000 0.50000 0.90000 0.50000 1.00000 0.40000 1.00000) + 4 V(104 105 116 115) M(0) UV(0.50000 0.90000 0.60000 0.90000 0.60000 1.00000 0.50000 1.00000) + 4 V(105 106 117 116) M(0) UV(0.60000 0.90000 0.70000 0.90000 0.70000 1.00000 0.60000 1.00000) + 4 V(106 107 118 117) M(0) UV(0.70000 0.90000 0.80000 0.90000 0.80000 1.00000 0.70000 1.00000) + 4 V(107 108 119 118) M(0) UV(0.80000 0.90000 0.90000 0.90000 0.90000 1.00000 0.80000 1.00000) + 4 V(108 109 120 119) M(0) UV(0.90000 0.90000 1.00000 0.90000 1.00000 1.00000 0.90000 1.00000) + } +} +Eof diff --git a/script/default_system/img/Default_Background_IceMountain_Spell01.png b/script/default_system/img/Default_Background_IceMountain_Spell01.png new file mode 100644 index 0000000..119af7d Binary files /dev/null and b/script/default_system/img/Default_Background_IceMountain_Spell01.png differ diff --git a/script/default_system/img/Default_Background_IceMountain_Spell02.png b/script/default_system/img/Default_Background_IceMountain_Spell02.png new file mode 100644 index 0000000..c5f0a8a Binary files /dev/null and b/script/default_system/img/Default_Background_IceMountain_Spell02.png differ diff --git a/script/default_system/img/Default_Effect.png b/script/default_system/img/Default_Effect.png new file mode 100644 index 0000000..61b968d Binary files /dev/null and b/script/default_system/img/Default_Effect.png differ diff --git a/script/default_system/img/Default_MagicCircle.png b/script/default_system/img/Default_MagicCircle.png new file mode 100644 index 0000000..0e0d6a1 Binary files /dev/null and b/script/default_system/img/Default_MagicCircle.png differ diff --git a/script/default_system/img/Default_Shot.png b/script/default_system/img/Default_Shot.png new file mode 100644 index 0000000..4cacac2 Binary files /dev/null and b/script/default_system/img/Default_Shot.png differ diff --git a/script/default_system/img/Default_System.png b/script/default_system/img/Default_System.png new file mode 100644 index 0000000..99f86c3 Binary files /dev/null and b/script/default_system/img/Default_System.png differ diff --git a/script/default_system/img/Default_SystemBackground.png b/script/default_system/img/Default_SystemBackground.png new file mode 100644 index 0000000..975f560 Binary files /dev/null and b/script/default_system/img/Default_SystemBackground.png differ diff --git a/script/default_system/img/Default_SystemDigit.png b/script/default_system/img/Default_SystemDigit.png new file mode 100644 index 0000000..4bb15dc Binary files /dev/null and b/script/default_system/img/Default_SystemDigit.png differ diff --git a/script/default_system/se/seGetSpellCardBonus.wav b/script/default_system/se/seGetSpellCardBonus.wav new file mode 100644 index 0000000..dec1071 Binary files /dev/null and b/script/default_system/se/seGetSpellCardBonus.wav differ diff --git a/script/default_system/se/seUseSpellCard.wav b/script/default_system/se/seUseSpellCard.wav new file mode 100644 index 0000000..bab7a69 Binary files /dev/null and b/script/default_system/se/seUseSpellCard.wav differ diff --git a/script/game/resourceLib/bossBoom.wav b/script/game/resourceLib/bossBoom.wav new file mode 100644 index 0000000..5af662b Binary files /dev/null and b/script/game/resourceLib/bossBoom.wav differ diff --git a/script/game/resourceLib/dialogueblip.wav b/script/game/resourceLib/dialogueblip.wav new file mode 100644 index 0000000..8f78fc7 Binary files /dev/null and b/script/game/resourceLib/dialogueblip.wav differ diff --git a/script/player/Chimata/Chimata_Function.dnh b/script/player/Chimata/Chimata_Function.dnh new file mode 100644 index 0000000..a4bee70 --- /dev/null +++ b/script/player/Chimata/Chimata_Function.dnh @@ -0,0 +1,489 @@ + +task _LaserSpriteRender( + img, int target, float targetAng, + int rectLeft, int rectTop, int rectRight, int rectBottom, + float scaleX, float scaleY, int renderPriority, float alpha, + float scaleSpeed + ){ + + let lasersprite = ObjPrim_Create(OBJ_SPRITE_2D); + + ObjPrim_SetTexture(lasersprite, img); + ObjSprite2D_SetSourceRect(lasersprite, rectLeft, rectTop, rectRight, rectBottom); + ObjRender_SetScaleXYZ(lasersprite, 0, scaleY, 1); + ObjSprite2D_SetDestRect(lasersprite, -(rectRight-rectLeft)/2, 0, (rectRight-rectLeft)/2, rectTop-rectBottom); + Obj_SetRenderPriorityI(lasersprite, renderPriority); + ObjRender_SetAlpha(lasersprite, 0); + ObjRender_SetBlendType(lasersprite, BLEND_ADD_ARGB); + + async{ + loop{ + int[] EnemyList = ObjCol_GetListOfIntersectedEnemyID(target); + if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE && !ripplayer && IsPermitPlayerShot){ + + // Assumes the intersecting color is right next to the right of the original color + + if (length(EnemyList) > 0) {ObjSprite2D_SetSourceRect(lasersprite, rectRight, rectTop, rectRight+(rectRight-rectLeft), rectBottom);} + else{ObjSprite2D_SetSourceRect(lasersprite, rectLeft, rectTop, rectRight, rectBottom);} + float targetx = ObjRender_GetX(target); + float targety = ObjRender_GetY(target); + ObjRender_SetScaleX(lasersprite, min(scaleX+rand(-0.025, 0.025), ObjRender_GetScaleX(lasersprite) + scaleSpeed)); + ObjRender_SetAlpha(lasersprite, min(alpha, ObjRender_GetAlpha(lasersprite)+alpha/5)); + ObjRender_SetAngleZ(lasersprite, targetAng); + ObjRender_SetPosition(lasersprite, targetx, targety, 1); + yield; + } + else{ + ObjRender_SetScaleX(lasersprite, max(0, ObjRender_GetScaleX(lasersprite) - scaleSpeed)); + ObjRender_SetAlpha(lasersprite, max(0, ObjRender_GetAlpha(lasersprite)-alpha/5)); + yield; + } + yield; + } + } + +} + +function _RenderLaser(target, float ang, float maxintersectX, float maxLength, float width, float speedLength, float dmg){ /* */ + + float angRender = asin(maxintersectX/absolute(maxLength)); + //int laser = CreatePlayerShotA1(ObjRender_GetX(target), ObjRender_GetY(target), 0, ang, dmg, 9999999, 0); + int laser = CreateStraightLaserA1(ObjRender_GetX(target), ObjRender_GetY(target), ang-90, maxLength, width, 9999999, 0, 1); + ObjLaser_SetInvalidLength(laser, 0, 0); + ObjShot_SetDamage(laser, dmg); + ObjShot_SetAutoDelete(laser, false); + Obj_SetRenderPriorityI(laser, 38); + _Follow(laser, target); + + _LaserSpriteRender( + teamimg, laser, ang, + 3072, 0, 3072+256, 256, + 0.45, 20, 38, 240, + 0.14 + ); + + // When shot key is being held, create a line intersection that stretches across the laser. + + /* + Calculations: + + startx: x of target + + starty: y of target + + endx: x of laser + + endy: maxLength + + width = width of laser + */ + async{ + + loop{ + + if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE && !ripplayer && IsPermitPlayerShot){ + + if(shotspeed % 5 == 0){ObjSound_Play(Fire);} + ObjShot_SetIntersectionEnable(laser, true); + //ObjShot_SetIntersectionLine(laser, ObjRender_GetX(target), ObjRender_GetY(target), ObjRender_GetX(target)+maxintersectX, -maxLength, width); + //WriteLog(ObjMove_GetX(laserfwd)); + yield; + + } + + else{ObjShot_SetIntersectionEnable(laser, false); yield;} + + } + + } + + // After shot key is released, let the laser leave and then delete it. + + return laser; +} + + +task _Follow(follower, followed){ + + while(!Obj_IsDeleted(follower)){ + float x = ObjRender_GetX(followed); + float y = ObjRender_GetY(followed); + ObjMove_SetPosition(follower, x, y); + yield; + } + +} + +// Special functions for Tenshi's CAVE laser shottype. +// Original code by Razzy/Razzly, edited and tweaked by Kevinmonitor + +// DEBUG + +float LaserAlpha = 0; // Not used + +task _CAVELaser(){ + + InitPLaserGfx(); // Probably effects that occur when the laser reaches an enemy? (KEV) + + let lasers0 = [ID_INVALID,ID_INVALID,ID_INVALID,ID_INVALID,ID_INVALID,ID_INVALID,ID_INVALID,ID_INVALID,ID_INVALID]; + + // this delays when the laser fires + // laser fires when laserMode==0 + // laserMode increments by 1 per frame + // so laser fires after 15 frames + + // KEV: To fire the laser immediately, just set laserMode/laserLimit to 0. + + let laserLimit = 0; + let laserMode=-laserLimit; + + loop{ + if( + GetPlayerState!=STATE_HIT + && GetPlayerState!=STATE_DOWN + && GetPlayerState!=STATE_END + && (GetVirtualKeyState(VK_SHOT)==KEY_PUSH || GetVirtualKeyState(VK_SHOT)==KEY_HOLD) + ){ + + if(IsPlayerSpellActive()){ + laserMode=min(0,laserMode+1); + } + + else{ + // reset laser delay when slowmove is let go + laserMode=-laserLimit; + } + + laserMode=min(0,laserMode+1); + + if(laserMode>=0){ + let odd = 1; + + //NonPenetrationLaser(obj, xoff, yoff, ang, spd, maxLen, dmg, IsStrongLaser, width, vwidth) + // KEV: Ascent loop determines the number of lasers that will be spawned. + + ascent(i in 0..1){ + let las = lasers0[i]; + if(Obj_IsValueExists(las,"DEL") || Obj_IsDeleted(las)){ + let magnitude = 1; + lasers0[i]=NonPenetrationLaser(objPlayer, 0, -36, 270, 40, GetStgFrameHeight()*1.5, 7, 1.25, 1); + } + odd=-odd; + } + //PlaySnd(SND_p_shot, 93); + } + + else{ + // reset laser delay when fire is let go + // KEV: Unnecessary if the laser fires immediately + RemovePLaserGfx(); + LaserAlpha = 0; + laserMode=-laserLimit; + } + + } + yield; + } +} + + // of an array of 2d coords, return the one closest to (sx,sy). Also returns the distance from (sx,sy) as the third value. + function GetClosestCoord(coords, sx,sy){ + let closest=[]; + let last_dist=99999; + let arrayLen=length(coords); + if(arrayLen==1){ + let cur_dist; + if(length(coords[0])==3){ cur_dist=coords[0][2]; } + else{ cur_dist=((coords[0][0]-sx)^2+(coords[0][1]-sy)^2)^0.5; } + closest=[coords[0][0],coords[0][1], cur_dist]; + } + else{ + ascent(i in 0..arrayLen){ + let cur_dist; + if(length(coords[i])==3){ cur_dist=(coords[i][2]); } + else{ cur_dist=((coords[i][0]-sx)^2+(coords[i][1]-sy)^2)^0.5; } + if(cur_dist < last_dist){ + last_dist=cur_dist; + closest=[coords[i][0], coords[i][1], cur_dist]; + } + } + } + return closest; + } + + // non-penetrating laser object + function NonPenetrationLaser(obj, xoff, yoff, ang, spd, maxLen, dmg, width, vwidth){ + + //KEV: Parameter explanations: + + //obj: Where the laser is fired from + //xoff/yoff: x and y offsets relative to the object + //ang, spd: Self-explanatory + //maxLen: max length of the laser, DON'T SET THIS TOO HIGH! GetStgFrameHeight() + a generous number should be enough + //dmg: Self-explanatory + //IsStrongLaser (REMOVED HERE): use this if you want to differentiate between strong and weak lasers I guess, I don't play CAVE games so idk + //width, vwidth: intersection & render width of laser + + // KEV: Defines the laser object. + + int a = 0; + + let damager = ObjShot_Create(OBJ_STRAIGHT_LASER); + + ObjShot_SetGraphic(damager, 0); + Obj_SetVisible(damager, true); + ObjShot_Regist(damager); + ObjShot_SetDamage(damager, dmg); + ObjShot_SetPenetration(damager, 9999); + ObjShot_SetEraseShot(damager, true); + ObjLaser_SetLength(damager, 0); + ObjLaser_SetIntersectionWidth(damager, 256*width); + ObjLaser_SetRenderWidth(damager, 256*vwidth); + ObjStLaser_SetAngle(damager, ang); ObjShot_SetAutoDelete(damager, false); + ObjShot_SetIntersectionEnable(damager, true); + TNonPenetrationLaser(); + + return damager; + + task TNonPenetrationLaser(){ + + let scroll=rand(0,64); + let len=0; // the length of the laser (increased until maxLen) + let cosine=cos(ang); // grab this value for placement of the tip. **this assumes the laser never changes angle** + let sine=sin(ang); // grab this value for placement of the tip. **this assumes the laser never changes angle** + + // **for lasers that change angle, cosine and sine will need to be updated** + + // Laser is now firing + while( + IsPlayerSpellActive() + && !Obj_IsDeleted(damager) // KEV: The four following states can be reduced to !ripplayer in my player scripts + && !ripplayer + && (GetVirtualKeyState(VK_SHOT) != KEY_FREE) + ){ + + a++; + if(a % 5 == 0){ObjSound_Play(Fire);} + CheckLaserIntersection; + // Set the laser's position and length + ObjMove_SetPosition(damager, ObjMove_GetX(obj)+xoff,ObjMove_GetY(obj)+yoff); + len = min(maxLen, len+spd); + ObjLaser_SetLength(damager, len); + //ObjShot_SetIntersectionLine(damager, ObjMove_GetX(obj), ObjMove_GetY(obj)+yoff, ObjMove_GetX(obj), -len, 128*width); + MakeLaserGfxFrame; + yield; + + } + + // This laser isn't deleted just yet. I let it fly away first. + // This value lets other tasks check when this happens. + Obj_SetValue(damager, "DEL", true); + + // Laser is now leaving + ObjMove_SetAngle(damager, ObjStLaser_GetAngle(damager)); + ObjMove_SetSpeed(damager, spd); + while(!Obj_IsDeleted(damager) && len > 128){ + MakeLaserGfxFrame; + len=max(0,len-spd); + ObjLaser_SetLength(damager, len); + CheckLaserIntersection; + yield; + } + Obj_Delete(damager); + + function MakeLaserGfxFrame(){ + //let hyper=0; + + // Values related to graphic lengths + + let gLen = max(0, len-32-24); + let gLen2 = max(0, len-32); + + // add sprites to the per-frame sprite list + + // KEV: Function reference: PLaserGfxFrameLaser(gfxObj, u, v, u2, v2, ry, x, y, ang, sx, sy, rd, gn, bl, al) + + //KEV: Function description: + + //Adds a vertex to the attached gfxObj sprite list. Uses u, v, u2, v2 as coordinates for the SourceRect, ry for DestRect (rx is calculated in the function), x & y for vertex position, sx & sy for the scaling, rd, gn and bl for colors, and al for alpha. + + //PLaserGfxFrame is similar but is used for the base and tip of the laser. The ry (and by extension rx) parameters are removed. + + //(rd, gn, bl values have been removed) + + // ObjStLaser_SetEndGraphic (ph3sx) may come in handy for the base/tips. + + // After reaching the bottom rect, value loops back to the top. + + PLaserGfxFrameLaser(lasGfxObj[0], 512, scroll, 1024, scroll*512, 64, ObjMove_GetX(damager)+cosine*24, ObjMove_GetY(damager)+sine*24, ang+90, vwidth*rand(1.0, 1.05), gLen/64, 255); + + PLaserGfxFrameLaser(lasGfxObj[1], 512, scroll, 1024, scroll*512, 64, ObjMove_GetX(damager)+cosine*24, ObjMove_GetY(damager)+sine*24, ang+90, vwidth*rand(1.4, 1.5), gLen/64, 60); // Glow effect + + PLaserGfxFrame(lasGfxObj[2], 512, 768, 1024, 1280, ObjMove_GetX(damager)+cosine*24, ObjMove_GetY(damager)+sine*24-20, ang+90, 1.15*vwidth+rand(0.2, 0.3), 1.15+rand(0.2, 0.3), 255); // Base of laser + + PLaserGfxFrame(lasGfxObj[3], 1024, 0, 1536, 512, ObjMove_GetX(damager)+cosine*gLen2, 10+ObjMove_GetY(damager)+sine*gLen2, ang+90, 0.6*width+rand(0.2, 0.3), 0.8, 255);// Tip of laser + + ObjRender_SetAngleZ(lasGfxObj[2], ObjRender_GetAngleZ(lasGfxObj[2])+10); + //WriteLog([ObjMove_GetX(damager), ObjMove_GetY(damager)]); + + scroll += 0.05; // Scrolls the laser's graphic. + if (scroll >= 1) {scroll = 0.1;} + + } + + function CheckLaserIntersection(){ + // ------------------ Check for enemy collisions ------------------ + let enemies=ObjCol_GetListOfIntersectedEnemyID(damager); // Get enemy array + let closest=[]; + let arrayLen=length(enemies); + // Check all enemies hit (if any) + if(arrayLen>0){ + let enm_pos=[]; // will be a 2-dimensional array + + // KEV: If there is no strong/weak laser differentiation, this ascent loop can be removed entirely(?) + + ascent(i in 0..arrayLen){ // go through the enemies list + // Weaker lasers get pushed back by "popcorn" enemies. + + // KEV: I don't really want to implement strong/weak laser differentiations... + + if(ObjEnemy_GetInfo(enemies[i], INFO_LIFE) > 1){ + // There are multiple collisions per enemy to check as well + // It's rare that there's more than one, but it's allowed + + let pos=GetEnemyIntersectionPositionByIdA1(enemies[i]); // KEV: Returns the multiple hitboxes of the enemy as a 2D array, format is [index][x, y of hitbox]. + + //KEV: Further explanation (rough and probably incorrect); + + //An enemy has 2 hitboxes, one at coords [16, 16] and one at [32, 32]. + + //You get a 2D array named "coords" containing the coordinates of these 2 hitboxes by using GetEnemyIntersectionPositionByIdA1. + + //You then write this line "float num = coords[0][1];" and WriteLog() the value of num. + + //coords[0][1] corresponds to the y coordinate of the first hitbox, which would give you a num value of 16. + + let closest2=GetClosestCoord(pos, ObjMove_GetX(damager),ObjMove_GetY(damager)); + if(closest2[0]!=-1234){ + enm_pos=enm_pos~[closest2]; + } + } + } + closest = GetClosestCoord(enm_pos, ObjMove_GetX(damager),ObjMove_GetY(damager)); + } + // ------------------ ------------------ ------------------ + + // There has been a collision, dial back laser length to (roughly) the point of collision. + // (Roughly) because we can't get the exact location, and doing it ourselves requires finding the hitbox dimensions. + + // KEV: Getting the hitbox dimensions/locations should be perfectly possible with ph3sx's intersection-obtaining functions. Will need re-examining + + // Set the damage of the laser. + + float dmgBase = 12; + float dmgMax = 12; + + if(length(closest) > 0){ + let dist=closest[2]-16; + len=max(0,dist); + + // The laser deals higher damage the closer it is to the enemy. + + float ratioDist = 120/closest[2]; + + ObjShot_SetDamage(damager, Interpolate_Decelerate(dmgBase, dmgMax, min(1, ratioDist))); + + // The laser changes colours depending on distance. + + } + } + } + } // NonPenetrationLaser + + +let lasGfxObj=[]; // KEV: An array that will contain three sprite lists, rendering three different parts of the laser (base, body, tip). + +// KEV: Creates the sprite lists, assigns the texture to them, and adds them as indexes into lasGfxObj. + +task InitPLaserGfx(){ + + let imgLaser = GetCurrentScriptDirectory() ~ "./playerlib/Chimata_Sheet.png"; + + LoadTextureEx(imgLaser, true, true); // Loaded in main script + + ascent(i in 0..4){ + let gfx = ObjPrim_Create(OBJ_SPRITE_LIST_2D); + ObjSpriteList2D_SetAutoClearVertexCount(gfx, true); + ObjPrim_SetTexture(gfx, imgLaser); + Obj_SetRenderPriorityI(gfx, 41); + lasGfxObj = lasGfxObj~[gfx]; + //ObjRender_SetBlendType(lasGfxObj[i-1], BLEND_ADD_ARGB); + } + + async{ + while(length(lasGfxObj) >= 3){ + ObjRender_SetAngleZ(lasGfxObj[2], ObjRender_GetAngleZ(lasGfxObj[2])+10); + yield; + } + } + + //ObjRender_SetBlendType(lasGfxObj[2], BLEND_ADD_ARGB); + Obj_SetRenderPriorityI(lasGfxObj[2], 42); + +} + +task RemovePLaserGfx{ + let imgLaser = GetCurrentScriptDirectory() ~ "laser_fx.png"; + RemoveTexture(imgLaser); + + ascent(i in 0..length(lasGfxObj)){ + Obj_Delete(lasGfxObj[i]); + lasGfxObj[i]=ID_INVALID; + } +} + +// See the non-penetrating laser object task for information on these tasks. + +task PLaserGfxFrame( + int gfxObj, + float rectLeft, float rectTop, float rectRight, float rectBottom, + float posX, float posY, + float ang, + float scaleX, float scaleY, + float alpha){ + + if(gfxObj==ID_INVALID){return;} + + //ObjRender_SetBlendType(gfxObj, BLEND_ADD_ARGB); + ObjRender_SetPosition(gfxObj, posX, posY, 0); + ObjRender_SetAngleZ(gfxObj, ang); + ObjRender_SetScaleXYZ(gfxObj, scaleX, scaleY, 1); + ObjSpriteList2D_SetSourceRect(gfxObj, rectLeft, rectTop, rectRight, rectBottom); + ObjSpriteList2D_SetDestCenter(gfxObj); + ObjSpriteList2D_AddVertex(gfxObj); + ObjRender_SetAlpha(gfxObj, alpha); + +} + +task PLaserGfxFrameLaser( + int gfxObj, + float rectLeft, float rectTop, float rectRight, float rectBottom, + float destY, + float posX, float posY, + float ang, + float scaleX, float scaleY, + float alpha){ + + if(gfxObj==ID_INVALID){return;} + + //ObjRender_SetBlendType(gfxObj, BLEND_ADD_ARGB); + ObjRender_SetPosition(gfxObj, posX, posY,0); + ObjRender_SetAngleZ(gfxObj, ang); + ObjRender_SetScaleXYZ(gfxObj, scaleX, scaleY, 1); + ObjRender_SetAlpha(gfxObj, alpha); + ObjSpriteList2D_SetSourceRect(gfxObj, rectLeft, rectTop, rectRight, rectBottom); + let destX = (rectRight - rectLeft)/2; + ObjSpriteList2D_SetDestRect(gfxObj, -destX, 0, destX, -destY); + ObjSpriteList2D_AddVertex(gfxObj); + +} \ No newline at end of file diff --git a/script/player/Chimata/Chimata_Main.dnh b/script/player/Chimata/Chimata_Main.dnh new file mode 100644 index 0000000..567a1ff --- /dev/null +++ b/script/player/Chimata/Chimata_Main.dnh @@ -0,0 +1,634 @@ +#TouhouDanmakufu[Player] +#ScriptVersion[3] +#ID["Flandre"] +#Title["Flandre"] +#Text["E"] + +//#Image["./mariremi_lib/mariremi_illust.png"] + +#ReplayName["Flandre"] + +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" + +#include "script/KevinSystem/Kevin_PlayerLib.txt" +#include "script/KevinSystem/PlayerSoundLib.dnh" + +#include "./Chimata_Function.dnh" +#include "./Chimata_ShotConst.dnh" + +#include "script/KevinSystem/kevin_system/Kevin_ItemConst.txt" +#include "script/KevinSystem/kevin_system/Kevin_ItemLib.txt" + +float shotDamage = 2.4+(GetCommonData("Rank", 1)*0.3); +float shotScale = 0.6+(GetCommonData("Rank", 1)*0.125); +float shotSpeed = 50+(GetCommonData("Rank", 1)*1.5); + +let csd = GetCurrentScriptDirectory(); + +// Global Variables + +float maxX = GetStgFrameWidth(); +float maxY = GetStgFrameHeight(); + +// Images & Sound + +let teamimg = csd ~ "./playerlib/Flan_Sheet.png"; +LoadTextureEx(teamimg, true, true); +//ObjRender_SetTextureFilterMip(teamimg, FILTER_LINEAR); + +let sndpath = csd ~ "./sound"; + +// Other stuff + +float playerX = 0; +float playerY = 0; + +let objPlayer = GetPlayerObjectID(); +int plrender = Obj_GetRenderPriorityI(objPlayer); + +bool ripplayer = false; +float shotspeed = 0; +float bombrand = 0; + +bool bombenable = false; +bool focusactive = false; +bool ishoming = false; + +bool isChain = false; + +int[] _enemyArray = []; // Prepare an array to store enemy IDs for Kouda's homing shot +int[] _existArray = []; +int[] _shotArray = []; + +int grazecounter = 0; // For basic graze = PIV mechanic + +int shotAlpha = (GetAreaCommonData("Config", "PlayerShotOpacity", 60)*0.01)*255; +float[] PlayerSpd = [15.5, 7.5]; + +// Custom events for scoring mechanic + +const EV_PIV_100 = EV_USER + 100i; // Normal enemies and nons +const EV_PIV_250 = EV_USER + 101i; // Spells +const EV_PIV_500 = EV_USER + 102i; // Last Spells +const EV_PIV_2000 = EV_USER + 103i; // What. + +@Initialize{ + + if(!IsCommonDataAreaExists("PIV")){ + CreateCommonDataArea("PIV"); + SetAreaCommonData("PIV", "currentvalue", 10000); + SetAreaCommonData("PIV", "ChainAmount", 1); + } + else{} + + SetPlayerStateEndEnable(true); + + // Stuff + parameterrender(); + playerrender(); + Obj_SetRenderPriorityI(objPlayer, 43); + plrender = Obj_GetRenderPriorityI(objPlayer); + _SoundTask(); + + //SetIntersectionVisualization(true); // Debug + + _Mechanic(ripplayer, _enemyArray, _existArray, GetStgFrameWidth(), GetStgFrameHeight(), objPlayer, GetEnemyBossSceneObjectID(), 5, 2, 80); + _ShowChain(); + + _HitboxRender(ripplayer, objPlayer, teamimg, teamimg, 1280, 512, 1408, 640, 1536, 896, 2048, 1408, 0.3, 0.65); + SetShotAutoDeleteClip(256, 256, 256, 256); + + // Shot functions + + //SetPlayerSpell(99); + + _Countdown(); + _CAVELaser(); + _ShotType(); + //UniversalAlphaHandle(_shotArray); + + // Shot data loading + LoadPlayerShotData(csd ~ "./Chimata_ShotData.dnh"); +} + +@MainLoop{ + _enemyArray = GetIntersectionRegistedEnemyID; + shotspeed += 1; // Managing the shot rate + //_shotArray = GetAllShotID(TARGET_PLAYER); + //UniversalAlphaHandle(_shotArray); + playerX = ObjMove_GetX(objPlayer); + playerY = ObjMove_GetY(objPlayer); + yield; +} + +@Event{ + alternative(GetEventType) + + // Delete effect + case(EV_DELETE_SHOT_PLAYER){ + + if(GetCommonDataPtr(EFFECTCUT_PTR, 0) >= 3){} + + else{ + let graphic = GetEventArgument(2); + float[] position = GetEventArgument(1); + let obj = CreatePlayerShotA1(position[0], position[1], 0, ObjMove_GetAngle(GetEventArgument(0)), 0, 99999, graphic); + ObjShot_SetIntersectionEnable(obj, false); _DeleteEffect(obj, shotScale); + } + //if(graphic == ELECTRIC_FIRE_ALT) {_DeleteEffectAlt(obj);} + //else{_DeleteEffect(obj);} + } + + // PIV-item spawning events + case(EV_PIV_100){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_100, arg[0], arg[1]); + } + + case(EV_PIV_250){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_250, arg[0], arg[1]); + } + + case(EV_PIV_500){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_500, arg[0], arg[1]); + } + + // Basic functionality events + case(EV_REQUEST_SPELL){ + let bomb = GetPlayerSpell(); + + if (bomb >= 1){ + SetScriptResult(true); + SetPlayerSpell(bomb - 1); + _Bomb(); + SetCommonData("Rank", max(1, GetCommonData("Rank", 1)-1)); + _SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, GetPlayerInvincibilityFrame()); + } + + else { + SetScriptResult(false); + } + } + + case(EV_HIT){ + ObjSound_Play(PlayerHit); + _DeathbombWarning(teamimg, [1536, 384, 1536+512, 384+512], 15, 0.75); + } + + case(EV_CHAIN_MAX){ + + if(!isChain){ + ObjSound_Play(Shine); + isChain = true; + } + else{} + + } + + case(EV_CHAIN_RELEASE){ + + } + + case(EV_CHAIN_END){ + SetAreaCommonData("PIV", "ChainAmount", 1); + isChain = false; + } + + case(EV_PLAYER_SHOOTDOWN){ + ObjSound_Play(PlayerDie2); + BombRefund(); + ripplayer = true; + DeleteShotAll(TYPE_SHOT, TYPE_ITEM); + SetCommonData("Rank", max(1, round(GetCommonData("Rank", 1)/2))); + _SigilCall(true, teamimg, 768, 512, 768+256, 768, objPlayer, 60); + } + + case(EV_PLAYER_REBIRTH){ + ripplayer = false; + SetPlayerInvincibilityFrame(180); + //_Countdown(); + _SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, 150); + + } + + case(EV_GRAZE){ + grazecounter += GetEventArgument(0); + ObjSound_Play(Graze); + while(grazecounter >= 10){ + SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue")+10); + grazecounter -= 10; + } + } +} + +@Finalize{ + +} + +// Homing +task BombRefund(){ + SetPlayerSpell(GetPlayerSpell()+[1, 2, 3, 3][clamp((GetCommonData("Rank", 1)/2)-1, 0, 3)]); +} + +task _SwingBehaviour(target){ + float ang = 0; + Obj_SetRenderPriorityI(target, 42); + while(true){ + ObjRender_SetAngleZ(target, 0+20*sin(ang)); + ang += 360/120; + yield; + } +} + +task _ShotType(){ + + _Option(125, 0, 0, 1); + _Option(125, 90, 0, 1); + _Option(125, 180, 0, 1); + _Option(125, 270, 0, 1); + + // Rank + + while(true){ + + shotDamage = 2.4+(GetCommonData("Rank", 1)*0.2); + shotScale = 0.6+(GetCommonData("Rank", 1)*0.1); + shotSpeed = 50+(GetCommonData("Rank", 1)*2); + + wait(30); + } + +} + +function _Option(dist, startang, wvel, counterspin){ + + //let shot = CreatePlayerShotA1(playerX+x, playerY-150+y, 0, startang, 0, 99999, KEV_OPTION); + let dummy = CreatePlayerShotA1(playerX, playerY-180, 0, startang, 0, 99999, 0); + + bool visible = true; + + int shotspeedhome = 0; + float counter = 0; + + float scythex = 0; + float scythey = 0; + + float offset = 0; + + float dummyX = ObjMove_GetX(dummy); + float dummyY = ObjMove_GetY(dummy); + + let shot = CreatePlayerShotA1(dummyX, dummyY, 0, startang, 0, 99999, OPTION); + + float spaceX = 0, spaceY = 0; + float shotang = startang; + + //ObjShot_SetSpinAngularVelocity(shot, wvel); + ObjShot_SetAutoDelete(shot, false); + ObjShot_SetAutoDelete(dummy, false); + + _BulletRescalePlayer(shot, 0.25, true, 1); + ObjRender_SetBlendType(shot, BLEND_ALPHA); + ObjRender_SetAlpha(shot, 255); + Obj_SetRenderPriorityI(shot, plrender-1); + + // Handles the spinning and shooting of the options. + async{ + + //SetShotAutoDeleteClip(-500, 128, -500, -500); + + //int i = 0; + + loop{ + + float shotx = ObjMove_GetX(shot); + float shoty = ObjMove_GetY(shot); + + ObjRender_SetAngleZ(shot, 0); + + if(!IsPermitPlayerShot || ripplayer){ + + //spaceX = clamp(spaceX-2, 0, x); + + //Obj_SetVisible(shot, false); + Obj_SetVisible(dummy, false); + visible = false; + shotspeedhome = 0; + + } + + else{ + + //spaceX = min(x, spaceX+x/45); + //spaceY = min(y, spaceY+y/45); + + Obj_SetVisible(shot, true); visible = true; + Obj_SetVisible(dummy, true); + + if(shotspeedhome % 4 == 0 && GetVirtualKeyState(VK_SHOT) != KEY_FREE){ + + let water = CreatePlayerShotA1(shotx, shoty, 50, 270, 4, 1.5, FIRE); + + //let water2 = CreatePlayerShotA1(shotx+25, shoty, 15, shotang+180, 1.82, 1.25, KEV_OPTIONSHOT); + + ObjShot_SetAutoDelete(water, false); + + ObjRender_SetAlpha(water, shotAlpha); + + _HandleDeletion(water); + + _BulletRescalePlayer(water, shotScale, true, 1); + + //ObjMove_SetAngularVelocity(water, [0, 0.2][typeGun]); + //ObjMove_SetAngularVelocity(water2, [0, 0.2][typeGun]); + + Obj_SetRenderPriorityI(water, plrender-1); + + ObjSound_Play(Base2); + } + shotspeedhome++; + //counter; + } + + yield; + } + } + + task _HandleDeletion(int target){ + + while(ObjMove_GetY(target) > -128){ + if(Obj_IsDeleted(target)){break;} + yield; + } + Obj_Delete(target); + return; + + } + + // Having the options move with Kevin if not shooting and/or focused. + async{ + float angmove = 0; + + loop{ + + ObjMove_SetPosition(shot, playerX+counterspin*spaceX*cos(shotang), playerY-offset+counterspin*spaceY*sin(shotang)); + shotang += 3.5*counterspin; + + ObjMove_SetPosition(dummy, playerX, playerY); + + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + + spaceX = max(dist*0.75, spaceX-dist*1.5/15); + spaceY = max(dist*0.75, spaceY-dist*1.5/15); + + } + + else{ + + spaceX = min(dist*1.5, spaceX+dist*1.5/15); + spaceY = min(dist*1.5, spaceY+dist*1.5/15); + + } + + yield; + } + } + + async{ + loop{ + + if(visible == true){ObjShot_SetIntersectionEnable(shot, true); ObjShot_SetIntersectionEnable(dummy, true); counter += (1/240); counter = min(counter, 1);} + + else if (visible != true && GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ObjShot_SetIntersectionEnable(shot, false); ObjShot_SetIntersectionEnable(dummy, false);} + + else {ObjShot_SetIntersectionEnable(shot, false); ObjShot_SetIntersectionEnable(dummy, false); counter = 0;} + yield; + } + } + + return shot; + +} + +// Basic player parameters + +task parameterrender(){ + + SetPlayerItemScope(120); + SetPlayerLife(9); // Debug + SetPlayerSpell(2); + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); // (original: 5.25/2.0) + SetPlayerRebirthFrame(15); + SetPlayerDownStateFrame(60); + SetPlayerAutoItemCollectLine(GetStgFrameHeight/3); + SetPlayerRebirthLossFrame(0); + ObjPlayer_AddIntersectionCircleA1(objPlayer, 0, 0, 0, 40); + +} + +// Renders the shottype +// Player sprites + +task playerrender(){ + + // Why is this movement code so cursed jesus fucking christ + + float scale = 0.4; // Scalies + int frame = 0; + + ObjPrim_SetTexture(objPlayer, teamimg); + ObjSprite2D_SetSourceRect(objPlayer, 0, 0, 512, 384); + ObjSprite2D_SetDestCenter(objPlayer); + Obj_SetRenderPriorityI(objPlayer, 42); + //ObjRender_SetTextureFilterMin(objPlayer, FILTER_ANISOTROPIC); + ObjRender_SetScaleXYZ(objPlayer, scale, scale, 1); + + // Lower "speed" parameter = FASTER SPEED + + // FOR WHEN ONLY IDLE SPRITES ARE DONE + + loop{ + //frame++; + _RenderPlayerMovement(objPlayer, frame, 0, 0, 512, 384, scale, 4, 6); + //if (frame >= (1*4-1)){frame = 0;} + yield; + } + +} + +task PointblankPlacebo(target, scale, multiplier){ + int len = 10; + while(GetObjectDistance(target, objPlayer) < 90){ + _BulletRescalePlayer(target, scale*multiplier, true, multiplier); // Pointblank + yield; + } + ascent(i in 0..len){ + _BulletRescalePlayer(target, Interpolate_Decelerate(scale*multiplier, scale, i/len), true, Interpolate_Decelerate(multiplier, 1, i/len)); + yield; + } +} + +task Fadein(target, len){ + ascent(i in 0..len){ + _BulletRescalePlayer(target, Interpolate_Decelerate(0.4, 0.7, i/len), true, Interpolate_Decelerate(0.4, 0.7, i/len)); + //ObjRender_SetBlendType(target, BLEND_ADD_ARGB); + yield; + } + ObjRender_SetBlendType(target, BLEND_ALPHA); +} + +task Fadein(target, len, targetscale, targetscalehitbox){ + ascent(i in 0..len){ + _BulletRescalePlayer(target, Interpolate_Decelerate(0.1, targetscale, i/len), true, Interpolate_Decelerate(1, targetscalehitbox, i/len)); + //ObjRender_SetBlendType(target, BLEND_ADD_ARGB); + yield; + } + ObjRender_SetBlendType(target, BLEND_ALPHA); +} + +// Handling of bomb + +task _Bomb(){ + + // Preparation + + SetAreaCommonData("ChainChecks", "IsChaining", true); + + SetForbidPlayerShot(true); + SetForbidPlayerSpell(true); + SetPlayerInvincibilityFrame(270); + // Spell object + let manageObj = GetSpellManageObject(); // SPELL BEGINS + ObjSpell_Regist(manageObj); + //ObjSound_Play(bombsfx); + SetPlayerSpeed(PlayerSpd[0]*2, PlayerSpd[1]*2); + + // 180 seconds DEATH LASER + + //SetCommonData("IsBomb", true); + + //_Countdown(270); + + async{ + loop(90){ + Fire(); + Fire(); + wait(2); + } + } + + function Fire(){ + let shotA = CreatePlayerShotA1(playerX, playerY, 25, rand(-15, 195), shotDamage/2, 25, FIRE); + _BulletRescalePlayer(shotA, 1.25, true, 1); + ObjRender_SetAlpha(shotA, 255); + Fading(shotA); + ObjRender_SetBlendType(shotA, BLEND_ADD_ARGB); + Obj_SetRenderPriorityI(shotA, 41); + ObjShot_SetPenetrateShotEnable(shotA, false); + //ObjShot_SetEnemyIntersectionInvalidFrame(shotA, 5); // CURRENTLY BUGGED AS OF PH3SX 1.32B + ObjShot_SetSpellFactor(shotA, true); + ObjShot_SetEraseShot(shotA, true); + } + + loop(30){ + if(GetVirtualKeyState(VK_SHOT) != KEY_FREE){ObjSound_Play(Fire);} + wait(6); + } + + task Fading(shot){ + ObjMove_SetAcceleration(shot, -1.5); + ObjMove_SetMaxSpeed(shot, 3); + ascent(i in 0..40){ + ObjRender_SetAlpha(shot, Interpolate_Decelerate(255, 0, i/40)); + yield; + } + Obj_Delete(shot); + } + + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); + SetForbidPlayerShot(false); + Obj_Delete(manageObj); // !!! IMPORTANT !!! + + SetAreaCommonData("ChainChecks", "IsChaining", false); + NotifyEventOwn(EV_CHAIN_END, 0); + + wait(60); + SetForbidPlayerSpell(false); + +} + +// Screenshake function for bomb's duration - adapted from Sparen's tutorials + +task _Countdown(){ + + //int timer = time; + int counter = CreateTextObject( + playerX, playerY, 58, + "", "Origami Mommy", + 0xFFFFFF, 0xFFFFFF, + 0x1AEC8C, 10, + Obj_GetRenderPriorityI(objPlayer)+1 + ); + + ObjText_SetHorizontalAlignment(counter, ALIGNMENT_CENTER); + + while(true){ + + if(GetPlayerInvincibilityFrame() <= 0){Obj_SetVisible(counter, false);} + else{Obj_SetVisible(counter, true);} + ObjRender_SetPosition(counter, playerX, playerY - 140, 1); + ObjText_SetText(counter, IntToString(GetPlayerInvincibilityFrame())); + yield; + + } + + //Obj_Delete(counter); + +} + +task _BombShake(shaketime, intensity){ + + float baseintensity = intensity; + float shakeno = shaketime; + + ascent(i in 0..shakeno){ + Set2DCameraFocusX(GetStgFrameWidth/2 + rand(-intensity, intensity)); + Set2DCameraFocusY(GetStgFrameHeight/2 + rand(-intensity, intensity)); + intensity = Interpolate_Decelerate(0, baseintensity, 1-i/shakeno); + shaketime--; + yield; + } + + while(shaketime > 0){yield;} + + Set2DCameraFocusX(GetStgFrameWidth/2); + Set2DCameraFocusY(GetStgFrameHeight/2); + yield; +} + +function CreateTextObject( + float mx, my, size, + string text, font, + int colorTop, colorBottom, + int borderColor, borderWidth, + int renderPriority + ){ + + let obj = ObjText_Create(); + ObjText_SetText(obj, text); + ObjText_SetFontSize(obj, size); + ObjText_SetFontType(obj, font); + ObjText_SetFontColorTop(obj, colorTop); + ObjText_SetFontColorBottom(obj, colorBottom); + ObjText_SetFontBorderType(obj, BORDER_FULL); + ObjText_SetFontBorderColor(obj, borderColor); + ObjText_SetFontBorderWidth(obj, borderWidth); + Obj_SetRenderPriorityI(obj, renderPriority); + ObjRender_SetX(obj, mx); + ObjRender_SetY(obj, my); + return obj; + +} + diff --git a/script/player/Chimata/Chimata_ShotConst.dnh b/script/player/Chimata/Chimata_ShotConst.dnh new file mode 100644 index 0000000..ecee52c --- /dev/null +++ b/script/player/Chimata/Chimata_ShotConst.dnh @@ -0,0 +1,9 @@ +let current = GetCurrentScriptDirectory(); +let path = current ~ "Chimata_ShotData.dnh"; +LoadPlayerShotData(path); +// ----- + +const FIRE = 1; +const OPTION = 2; + + diff --git a/script/player/Chimata/Chimata_ShotData.dnh b/script/player/Chimata/Chimata_ShotData.dnh new file mode 100644 index 0000000..8569acd --- /dev/null +++ b/script/player/Chimata/Chimata_ShotData.dnh @@ -0,0 +1,30 @@ +shot_image = "./playerlib/Flan_Sheet.png" + +ShotData{ + id = 0 // Dummy + rect = (0,0,0,0) + render = ALPHA + alpha = 0 + collision = 32 +} + +// Fire + +ShotData{ + id = 1 + rect = (1024, 0, 1152, 256) + render = ALPHA + alpha = 255 + collision = 128 // Hitbox of arrows is not centered on the sprite +} + +// Option + +ShotData{ + id = 2 + rect = (512, 0, 1024, 384) + render = ALPHA + alpha = 255 + fixed_angle = true + collision = 0 // Hitbox of arrows is not centered on the sprite +} \ No newline at end of file diff --git a/script/player/Chimata/desc.txt b/script/player/Chimata/desc.txt new file mode 100644 index 0000000..e69de29 diff --git a/script/player/Chimata/playerlib/Chimata_Sheet.png b/script/player/Chimata/playerlib/Chimata_Sheet.png new file mode 100644 index 0000000..3237502 Binary files /dev/null and b/script/player/Chimata/playerlib/Chimata_Sheet.png differ diff --git a/script/player/Chimata/playerlib/Flan_Sheet.png b/script/player/Chimata/playerlib/Flan_Sheet.png new file mode 100644 index 0000000..d27263a Binary files /dev/null and b/script/player/Chimata/playerlib/Flan_Sheet.png differ diff --git a/script/player/Chimata/playerlib/Sheet.mdp b/script/player/Chimata/playerlib/Sheet.mdp new file mode 100644 index 0000000..c7bbc1f Binary files /dev/null and b/script/player/Chimata/playerlib/Sheet.mdp differ diff --git a/script/player/Chimata/playerlib/Sheet2.mdp b/script/player/Chimata/playerlib/Sheet2.mdp new file mode 100644 index 0000000..5b98aa0 Binary files /dev/null and b/script/player/Chimata/playerlib/Sheet2.mdp differ diff --git a/script/player/Chimata/sound/CK Music Factory/air01.wav b/script/player/Chimata/sound/CK Music Factory/air01.wav new file mode 100644 index 0000000..bc2c0ed Binary files /dev/null and b/script/player/Chimata/sound/CK Music Factory/air01.wav differ diff --git a/script/player/Chimata/sound/CK Music Factory/air02.wav b/script/player/Chimata/sound/CK Music Factory/air02.wav new file mode 100644 index 0000000..f7e5ed8 Binary files /dev/null and b/script/player/Chimata/sound/CK Music Factory/air02.wav differ diff --git a/script/player/Chimata/sound/CK Music Factory/laser01.wav b/script/player/Chimata/sound/CK Music Factory/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/Chimata/sound/CK Music Factory/laser01.wav differ diff --git a/script/player/Chimata/sound/CK Music Factory/slash01.wav b/script/player/Chimata/sound/CK Music Factory/slash01.wav new file mode 100644 index 0000000..364dfca Binary files /dev/null and b/script/player/Chimata/sound/CK Music Factory/slash01.wav differ diff --git a/script/player/Chimata/sound/CK Music Factory/wind01.wav b/script/player/Chimata/sound/CK Music Factory/wind01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/Chimata/sound/CK Music Factory/wind01.wav differ diff --git a/script/player/Chimata/sound/TAM Music Factory/se04.wav b/script/player/Chimata/sound/TAM Music Factory/se04.wav new file mode 100644 index 0000000..ca33890 Binary files /dev/null and b/script/player/Chimata/sound/TAM Music Factory/se04.wav differ diff --git a/script/player/Chimata/sound/TAM Music Factory/status4.wav b/script/player/Chimata/sound/TAM Music Factory/status4.wav new file mode 100644 index 0000000..1227a08 Binary files /dev/null and b/script/player/Chimata/sound/TAM Music Factory/status4.wav differ diff --git a/script/player/Chimata/sound/TAM Music Factory/tama2.wav b/script/player/Chimata/sound/TAM Music Factory/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/Chimata/sound/TAM Music Factory/tama2.wav differ diff --git a/script/player/Chimata/sound/bfxr_scythecall.wav b/script/player/Chimata/sound/bfxr_scythecall.wav new file mode 100644 index 0000000..99b3040 Binary files /dev/null and b/script/player/Chimata/sound/bfxr_scythecall.wav differ diff --git a/script/player/Chimata/sound/bfxr_splash.wav b/script/player/Chimata/sound/bfxr_splash.wav new file mode 100644 index 0000000..6a4d49d Binary files /dev/null and b/script/player/Chimata/sound/bfxr_splash.wav differ diff --git a/script/player/Chimata/sound/bfxr_teleporthigh.wav b/script/player/Chimata/sound/bfxr_teleporthigh.wav new file mode 100644 index 0000000..cc8b9ae --- /dev/null +++ b/script/player/Chimata/sound/bfxr_teleporthigh.wav @@ -0,0 +1 @@ +2,0.57,,0.3442,,0.2691,0.3,0.2179,,0.3445,,,,,,,,,,,0.2992,,0.5139,,,1,,,,,,,masterVolume \ No newline at end of file diff --git a/script/player/Chimata/sound/bfxr_teleportlow.wav b/script/player/Chimata/sound/bfxr_teleportlow.wav new file mode 100644 index 0000000..d55ce4b Binary files /dev/null and b/script/player/Chimata/sound/bfxr_teleportlow.wav differ diff --git a/script/player/Chimata/sound/bfxr_watershoot.wav b/script/player/Chimata/sound/bfxr_watershoot.wav new file mode 100644 index 0000000..6cfced3 Binary files /dev/null and b/script/player/Chimata/sound/bfxr_watershoot.wav differ diff --git a/script/player/Chimata/sound/birdcall05.wav b/script/player/Chimata/sound/birdcall05.wav new file mode 100644 index 0000000..ec6c7b9 Binary files /dev/null and b/script/player/Chimata/sound/birdcall05.wav differ diff --git a/script/player/Chimata/sound/hit01.wav b/script/player/Chimata/sound/hit01.wav new file mode 100644 index 0000000..0698a04 Binary files /dev/null and b/script/player/Chimata/sound/hit01.wav differ diff --git a/script/player/Chimata/sound/laser01.wav b/script/player/Chimata/sound/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/Chimata/sound/laser01.wav differ diff --git a/script/player/Chimata/sound/magic21.wav b/script/player/Chimata/sound/magic21.wav new file mode 100644 index 0000000..19714fe Binary files /dev/null and b/script/player/Chimata/sound/magic21.wav differ diff --git a/script/player/Chimata/sound/retrolaser.wav b/script/player/Chimata/sound/retrolaser.wav new file mode 100644 index 0000000..a58304e Binary files /dev/null and b/script/player/Chimata/sound/retrolaser.wav differ diff --git a/script/player/Chimata/sound/slash01.wav b/script/player/Chimata/sound/slash01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/Chimata/sound/slash01.wav differ diff --git a/script/player/Chimata/sound/tama2.wav b/script/player/Chimata/sound/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/Chimata/sound/tama2.wav differ diff --git a/script/player/Kouryuu/Player_Function.dnh b/script/player/Kouryuu/Player_Function.dnh new file mode 100644 index 0000000..f1dec6e --- /dev/null +++ b/script/player/Kouryuu/Player_Function.dnh @@ -0,0 +1,415 @@ +#include "./Player_Function_Laser.dnh" + +// Shot Type + +int[] optionArr = []; +float angSpace = 2.5; + +float[] angStartArr = []; + +// Far left, left, right, far right + +float[] angStartUF = [230, 270, 270, 310]; +float[] angStartUFAlt = [230, 275, 265, 310]; +float[] angStartF = [250, 280, 260, 290]; + +float offsetX = 125; +float offsetY = 75; + +int[] bulletNum = [4, 3, 3, 4]; + + +task _HomeShot(int shot_) { + + float duration = 55; + bool homingBool = false; + float basepenetrate = ObjShot_GetPenetration(shot_); + float basedmg = ObjShot_GetDamage(shot_); + + // + + for (int t = 0i; t < duration && !Obj_IsDeleted(shot_); t++) { + + // Checks if enemies are on screen. If enemies are visible, enable homing for the shots. + // _enemyArray is an array containing all enemy IDs, and is constantly updated in @MainLoop. + + if (0 < length(_enemyArray)) { + float targetDist = 2000; // Arbitrary number (???) + int targetID = 0; + + // Checks distance of every enemy on screen. + + for each (int enemy in ref _enemyArray) { + float enemyX = ObjMove_GetX(enemy); + float enemyY = ObjMove_GetY(enemy); + if (0 < enemyX && enemyX < maxX && 0 < enemyY && enemyY < maxY) { + + // Returns the hypotenuse of the triangle formed by the x & y distances between the shot and the enemy. + + float shotDist = hypot(enemyX - ObjMove_GetX(shot_), enemyY - ObjMove_GetY(shot_)); + + // Locks the shot onto the enemy. + + if (shotDist < targetDist) { + targetDist = shotDist; + targetID = enemy; + homingBool = true; + } + } + } + + // Code to handle the actual homing. + + if (homingBool) { + for (int f = 0; t < duration && !Obj_IsDeleted(shot_) && !Obj_IsDeleted(targetID) && ObjEnemy_GetInfo(targetID, INFO_LIFE) != 0 && !ObjCol_IsIntersected(shot_); t++) { + ObjShot_SetAutoDelete(shot_, false); + float shotAngle = NormalizeAngle(ObjMove_GetAngle(shot_)); // Angle of the player shot + float targetAngle = NormalizeAngle(atan2(ObjMove_GetY(targetID) - ObjMove_GetY(shot_), ObjMove_GetX(targetID) - ObjMove_GetX(shot_))); // Returns angle from the shot to the enemy. + float angleDistance = AngularDistance(shotAngle, targetAngle); // Angular distance between enemy and player shot + float homeRate = Interpolate_Decelerate(0, 0.8, min(45, f) / 45); + // Homing speed? + ObjMove_SetAngle(shot_, Interpolate_Accelerate(shotAngle, shotAngle + angleDistance, homeRate)); // Interpolate_Necko + f++; + yield; + } + ObjShot_SetAutoDelete(shot_, true); + ObjMove_SetAngularVelocity(shot_, 0); + homingBool = false; + } + } + + yield; + } +} + +task UpdateAng(){ + while(true){ + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + angStartArr = angStartF; + angSpace = 9; + } + else{ + angStartArr = angStartUF; + angSpace = 18; + } + yield; + } +} + +task ShotType(){ + +} + +function CreateOption(distX, distY, startang, wvel, counterspin){ + + //let shot = CreatePlayerShotA1(playerX+x, playerY-150+y, 0, startang, 0, 99999, KEV_OPTION); + let dummy = CreatePlayerShotA1(playerX, playerY-180, 0, startang, 0, 99999, 0); + + bool visible = true; + + int shotspeedhome = 0; + float counter = 0; + + float scythex = 0; + float scythey = 0; + + float offset = 0; + + float dummyX = ObjMove_GetX(dummy); + float dummyY = ObjMove_GetY(dummy); + + let shot = CreatePlayerShotA1(dummyX, dummyY, 0, startang, 0, 99999, OPTION); + + float spaceX = 0, spaceY = 0; + float shotang = startang; + + //ObjShot_SetSpinAngularVelocity(shot, wvel); + ObjShot_SetAutoDelete(shot, false); + ObjShot_SetAutoDelete(dummy, false); + + _BulletRescalePlayer(shot, 1, true, 1); + ObjRender_SetBlendType(shot, BLEND_ALPHA); + ObjRender_SetAlpha(shot, 255); + + float shotX = ObjMove_GetX(shot); + float shotY = ObjMove_GetY(shot); + + // Handles the spinning and shooting of the options. + + async{ + + //SetShotAutoDeleteClip(-500, 128, -500, -500); + + //int i = 0; + + loop{ + + shotX = ObjMove_GetX(shot); + shotY = ObjMove_GetY(shot); + + ObjRender_SetAngleZ(shot, 0); + + if(!IsPermitPlayerShot || ripplayer){ + + //spaceX = clamp(spaceX-2, 0, x); + + //Obj_SetVisible(shot, false); + Obj_SetVisible(dummy, false); + visible = false; + shotspeedhome = 0; + + } + + else{ + + //spaceX = min(x, spaceX+x/45); + //spaceY = min(y, spaceY+y/45); + + Obj_SetVisible(shot, true); + visible = true; + Obj_SetVisible(dummy, true); + + if(shotspeedhome % 4 == 0 && GetVirtualKeyState(VK_USER1) == KEY_FREE && GetVirtualKeyState(VK_SHOT) != KEY_FREE){ + + let bullet = CreatePlayerShotA1(shotX, shotY, 50, 270, shotDamageOption, 1.5, FIRE_OPTION); + + //let water2 = CreatePlayerShotA1(shotx+25, shoty, 15, shotang+180, 1.82, 1.25, KEV_OPTIONSHOT); + + ObjShot_SetAutoDelete(bullet, false); + _HandleDeletion(bullet); + + ObjRender_SetAlpha(bullet, shotAlpha); + + _BulletRescalePlayer(bullet, shotScaleOption, true, 1); + + //ObjMove_SetAngularVelocity(water, [0, 0.2][typeGun]); + //ObjMove_SetAngularVelocity(water2, [0, 0.2][typeGun]); + + Obj_SetRenderPriorityI(bullet, plrender-1); + + ObjSound_Play(Base2); + } + shotspeedhome++; + //counter; + } + + yield; + } + } + + task _HandleDeletion(int target){ + + while(ObjMove_GetY(target) > -96){ + if(Obj_IsDeleted(target)){break;} + yield; + } + Obj_Delete(target); + return; + + } + + // Having the options move with Kevin if not shooting and/or focused. + async{ + float angmove = 0; + + loop{ + + ObjMove_SetPosition(shot, playerX+counterspin*spaceX*cos(shotang), playerY-offset+counterspin*spaceY*sin(shotang)); + shotang += 3*counterspin; + + ObjMove_SetPosition(dummy, playerX, playerY); + + // If under player: render above + + if(shotY > playerY){Obj_SetRenderPriorityI(shot, plrender+1);} + else{Obj_SetRenderPriorityI(shot, plrender-1);} + + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + + spaceX = max(distX*0.6, spaceX-distX*1/15); + spaceY = max(distY*0.6, spaceY-distY*1/15); + + } + + else{ + + spaceX = min(distX*1, spaceX+distX*1/15); + spaceY = min(distY*1, spaceY+distY*1/15); + + } + + yield; + } + } + + async{ + loop{ + + if(visible == true){ObjShot_SetIntersectionEnable(shot, true); ObjShot_SetIntersectionEnable(dummy, true); counter += (1/240); counter = min(counter, 1);} + + else if (visible != true && GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ObjShot_SetIntersectionEnable(shot, false); ObjShot_SetIntersectionEnable(dummy, false);} + + else {ObjShot_SetIntersectionEnable(shot, false); ObjShot_SetIntersectionEnable(dummy, false); counter = 0;} + yield; + } + } + + return shot; + +} + +// CALL THIS TASK FIRST + +task InitiateOptions(){ + + // Far left, left, right, far right + + float distX = 175; + float distY = 175; + float[] angArr = [0, 90, 180, 270]; + + int count = 0; + + for each (float entry in ref angArr){ + + int option = CreateOption(distX, distY, angArr[count], 1, -1); + + optionArr = optionArr ~ [option]; + + count++; + + } + + SpecialWeapon(objPlayer); + +} + + +task BaseShot(){ + + int angMultiplier = 0; + + // lASER!!! + + _RenderLaser(objPlayer, 0, 300, GetStgFrameHeight()*1.5, 64, 0, shotDamageLaser); + +} + +task SpecialWeapon(int ID){ + + int angMultiplier = 0; + float angFlux = 10; + float ang1 = 180; + float ang2 = 180; + float[] angFire = [270-20, 270+20]; + + while(true){ + + if(GetVirtualKeyState(VK_USER1) != KEY_FREE && GetCommonDataPtr(POINTER_SPECIALAMMO, 100) > 0 && IsPermitPlayerShot && !ripplayer){ + + SetCommonDataPtr(POINTER_SPECIALCHECK, true); + SetCommonDataPtr(POINTER_CHAINCHECK, true); + + // (Approx.) 20 ammo per second + + SetCommonDataPtr(POINTER_SPECIALAMMO, max(0, GetCommonDataPtr(POINTER_SPECIALAMMO, 100)-(20/60))); + + if(shotspeed % 4 == 0){ + + float x = ObjMove_GetX(ID); + float y = ObjMove_GetY(ID); + + // Minimal rank boost -> +0.5 rank for every 10 seconds of the wpn being used -> 1/20 rank every sec -> 1/300 rank every 4 frames + + SetCommonData("Rank", clamp(GetCommonData("Rank", 1) + 1/300, GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); + + angFire[0] = 270 + angFlux * sin(ang1) + rand(-5, 5); + angFire[1] = 270 + angFlux * sin(ang2) + rand(-5, 5); + // YASS FIRE THOSE BITCH KILLER SLASHES + FireSlash(angFire[0], 50, 35, 45); + FireSlash(angFire[1], 50, 35, 45); + + ang1 += 25; + ang2 -= 25; + + } + + } + + else{ + + SetCommonDataPtr(POINTER_CHAINCHECK, false); + if(GetCommonDataPtr(POINTER_CHAINGAUGE, 0) <= 0){SetCommonDataPtr(POINTER_SPECIALCHECK, false);} + + } + + yield; + } + +} + +task FireSlash( + float angle, baseSpd, + int decelTime, lifeTime +){ + + int slash = CreatePlayerShotA1(playerX, playerY, baseSpd, angle, shotDamageSpecial, 8, FIRE_SPECIAL); + ObjShot_SetPenetrateShotEnable(slash, false); + _BulletRescalePlayer(slash, shotScaleSpecial, true, 1); + + Obj_SetRenderPriorityI(slash, plrender-1); + + //ObjRender_SetBlendType(slash, BLEND_ADD_ARGB); + ObjSound_Play(Base5); + ObjShot_SetEraseShot(slash, true); + + async{ + + ascent(i in 0..3){ + int slashA = CreatePlayerShotA1(playerX, playerY, baseSpd, angle, shotDamageSpecial/5, 32, FIRE_SPECIAL); + _BulletRescalePlayer(slashA, shotScaleSpecial/2, true, 1); + //ObjRender_SetBlendType(slashA, BLEND_ADD_ARGB); + ObjShot_SetPenetrateShotEnable(slashA, false); + Obj_SetRenderPriorityI(slashA, plrender-1); + Fade(slashA); + wait(10); + } + + } + + task Fade(int ID){ + + ObjMove_AddPatternA2(ID, 0, baseSpd/2, [rand(180, 230), rand(-50, 30)][rand_int(0, 1)], (-baseSpd/2)/(decelTime), 2, 0); + + ascent(i in 0..(decelTime)){ + ObjRender_SetAlpha(ID, Interpolate_Accelerate(shotAlpha, 0, i/(decelTime))); + yield; + } + + Obj_Delete(ID); + + } + + async{ + + ObjMove_SetAcceleration(slash, -baseSpd/decelTime); + ObjMove_SetMaxSpeed(slash, baseSpd/50); + ObjRender_SetAlpha(slash, shotAlpha); + + ascent(i in 0..decelTime){ + ObjRender_SetScaleXYZ(slash, Interpolate_Accelerate(shotScaleSpecial/1.25, shotScaleSpecial, i/decelTime)); + yield; + } + + ascent(i in 0..(lifeTime-decelTime)){ + ObjRender_SetAlpha(slash, Interpolate_Accelerate(shotAlpha, 0, i/(lifeTime-decelTime))); + yield; + } + + Obj_Delete(slash); + + } +} + +// Bomb +// Holy fuck its literally YoumuA IBP \ No newline at end of file diff --git a/script/player/Kouryuu/Player_Function_Laser.dnh b/script/player/Kouryuu/Player_Function_Laser.dnh new file mode 100644 index 0000000..8d55f67 --- /dev/null +++ b/script/player/Kouryuu/Player_Function_Laser.dnh @@ -0,0 +1,232 @@ + +// Particle list for laser effect + +int LaserEffect = ObjParticleList_Create(OBJ_PARTICLE_LIST_2D); +int[] rect = [704, 192, 768, 256]; + +ObjPrim_SetTexture(LaserEffect, "script/player/Kouryuu/playerlib/PlSheet_Kouryuu.png"); + +Obj_SetRenderPriorityI(LaserEffect, 41); +ObjPrim_SetPrimitiveType(LaserEffect, PRIMITIVE_TRIANGLELIST); +ObjPrim_SetVertexCount(LaserEffect, 4); + +ObjRender_SetBlendType(LaserEffect, BLEND_ADD_ARGB); + +// Left-top, right-top, left-bottom, right-bottom + +ObjPrim_SetVertexUVT(LaserEffect, 0, rect[0], rect[1]); +ObjPrim_SetVertexUVT(LaserEffect, 1, rect[2], rect[1]); +ObjPrim_SetVertexUVT(LaserEffect, 2, rect[0], rect[3]); +ObjPrim_SetVertexUVT(LaserEffect, 3, rect[2], rect[3]); + +// Vertex positions are offset with deltas so that the sprite is centered + +float dU = (rect[2] - rect[0])/2; +float dV = (rect[3] - rect[1])/2; + +ObjPrim_SetVertexPosition(LaserEffect, 0, -dU, -dV, 1); +ObjPrim_SetVertexPosition(LaserEffect, 1, dU, -dV, 1); +ObjPrim_SetVertexPosition(LaserEffect, 2, -dU, dV, 1); +ObjPrim_SetVertexPosition(LaserEffect, 3, dU, dV, 1); + +ObjPrim_SetVertexIndex(LaserEffect, [0, 1, 2, 1, 2, 3]); + +task _CreateLaserParticle(float x, float y, float spdX, float spdY, float baseAng){ + + int effectLength = 45; + let x_speed = spdX; + let y_speed = spdY; + let z_add = rand(-5, 5); + + ascent(i in 0..effectLength){ + _PetalMovement(Interpolate_Decelerate(1, 0.5, i/effectLength), Interpolate_Decelerate(255, 0, i/effectLength)); + yield; + } + + task _PetalMovement(scale, alpha){ + + ObjParticleList_SetScale(LaserEffect, scale); + ObjParticleList_SetAngleZ(LaserEffect, baseAng); + ObjParticleList_SetPosition(LaserEffect, x, y, 1); + ObjParticleList_SetAlpha(LaserEffect, alpha); + + //Submits the current data to an instance, cleared every frame. + ObjParticleList_AddInstance(LaserEffect); + + x += x_speed; + y += y_speed; + baseAng += z_add; + + yield; + + } + +} + +// + +task _LaserSpriteRender( + img, int target, float targetAng, + int rectLeft, int rectTop, int rectRight, int rectBottom, + float scaleX, float scaleY, int renderPriority, float alpha, + float scaleSpeed + ){ + + int[] EnemyList = []; + let lasersprite = ObjPrim_Create(OBJ_SPRITE_2D); + + float scaleXBoost = 0; + float scaleXBoostMax = 0.05; + float ang = 180; + + ObjPrim_SetTexture(lasersprite, img); + ObjSprite2D_SetSourceRect(lasersprite, rectLeft, rectTop, rectRight, rectBottom); + ObjRender_SetScaleXYZ(lasersprite, 0, scaleY, 1); + ObjSprite2D_SetDestRect(lasersprite, -(rectRight-rectLeft)/2, 0, (rectRight-rectLeft)/2, rectTop-rectBottom); + Obj_SetRenderPriorityI(lasersprite, renderPriority); + ObjRender_SetAlpha(lasersprite, 0); + ObjRender_SetBlendType(lasersprite, BLEND_ADD_ARGB); + + async{ + loop{ + + if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && !ripplayer && IsPermitPlayerShot){ + + // Assumes the intersecting color is right next to the right of the original color + + if (length(EnemyList) > 0) {ObjSprite2D_SetSourceRect(lasersprite, rectRight, rectTop, rectRight+(rectRight-rectLeft), rectBottom);} + else{ObjSprite2D_SetSourceRect(lasersprite, rectLeft, rectTop, rectRight, rectBottom);} + + float targetx = ObjRender_GetX(target); + float targety = ObjRender_GetY(target); + + ObjRender_SetScaleX(lasersprite, min(scaleX+scaleXBoost, ObjRender_GetScaleX(lasersprite) + scaleSpeed)); + scaleXBoost = scaleXBoostMax * sin(ang); + + ObjRender_SetAlpha(lasersprite, min(alpha, ObjRender_GetAlpha(lasersprite)+alpha/5)); + ObjRender_SetAngleZ(lasersprite, targetAng); + ObjRender_SetPosition(lasersprite, targetx, targety, 1); + + ang += 25; + + yield; + + } + + else{ + ObjRender_SetScaleX(lasersprite, max(0, ObjRender_GetScaleX(lasersprite) - scaleSpeed)); + ObjRender_SetAlpha(lasersprite, max(0, ObjRender_GetAlpha(lasersprite)-alpha/5)); + yield; + } + + yield; + } + } + +} + +function _RenderLaser(target, float ang, float maxintersectX, float maxLength, float width, float speedLength, float dmg){ /* */ + + int[] EnemyList = []; + + float angRender = asin(maxintersectX/absolute(maxLength)); + //int laser = CreatePlayerShotA1(ObjRender_GetX(target), ObjRender_GetY(target), 0, ang, dmg, 9999999, 0); + int laser = CreateStraightLaserA1(ObjRender_GetX(target), ObjRender_GetY(target), ang-90, maxLength, width, 99999999, 0, 1); + ObjLaser_SetInvalidLength(laser, 0, 0); + ObjShot_SetDamage(laser, dmg); + ObjShot_SetAutoDelete(laser, false); + Obj_SetRenderPriorityI(laser, plrender-1); + _Follow(laser, target); + + _LaserSpriteRender( + plimg, laser, ang, + 256, 192, 384, 384, + 1, 20, plrender-1, shotAlpha, + 0.1 + ); + + // This also affects damage of the laser, not just effects + LaserHitEffect(EnemyList, laser, dmg); + + // When shot key is being held, create a line intersection that stretches across the laser. + + /* + Calculations: + + startx: x of target + + starty: y of target + + endx: x of laser + + endy: maxLength + + width = width of laser + */ + async{ + + loop{ + + if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && !ripplayer && IsPermitPlayerShot){ + + if(shotspeed % 5 == 0){ + ObjSound_Play(Base2); + } + + ObjShot_SetIntersectionEnable(laser, true); + + //ObjShot_SetIntersectionLine(laser, ObjRender_GetX(target), ObjRender_GetY(target), ObjRender_GetX(target)+maxintersectX, -maxLength, width); + //WriteLog(ObjMove_GetX(laserfwd)); + yield; + + } + + else{ + ObjShot_SetIntersectionEnable(laser, false); + ObjShot_SetPenetration(laser, 99999999); + yield; + } + + } + + } + + // After shot key is released, let the laser leave and then delete it. + + return laser; +} + +task LaserHitEffect(int[] EnemyList, int target, float basedmg){ + + async{ + loop{ + EnemyList = ObjCol_GetListOfIntersectedEnemyID(target); + yield; + } + } + + // Particle effects + async{ + loop{ + ascent(i in -1..length(EnemyList)-1){ + _CreateLaserParticle(ObjMove_GetX(EnemyList[i])+prand(-30, 30), ObjMove_GetY(EnemyList[i])+prand(-30, 30), [prand(-8, -5), prand(-4, 4), prand(5, 8)][prand_int(0, 2)], [prand(-8, -6), prand(6, 8)][prand_int(0, 1)], rand(0, 360)); + } + //Resort; + //WriteLog(EnemyList); + wait(rand_int(6, 9)); + } + } + + // Damage effects + +} +task _Follow(follower, followed){ + + while(!Obj_IsDeleted(follower)){ + float x = ObjRender_GetX(followed); + float y = ObjRender_GetY(followed); + ObjMove_SetPosition(follower, x, y); + yield; + } + +} \ No newline at end of file diff --git a/script/player/Kouryuu/Player_Main.dnh b/script/player/Kouryuu/Player_Main.dnh new file mode 100644 index 0000000..3d8a359 --- /dev/null +++ b/script/player/Kouryuu/Player_Main.dnh @@ -0,0 +1,374 @@ +#TouhouDanmakufu[Player] +#ScriptVersion[3] +#ID["PL2_KOURYUU"] +#Title["Kouryuu Eikankaku"] +#Text["Player 2"] + +//#Image["./mariremi_lib/mariremi_illust.png"] + +#ReplayName["Kouryuu"] + +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" + +#include "script/KevinSystem/Kevin_PlayerLib.txt" +#include "script/KevinSystem/PlayerSoundLib.dnh" + +#include "./Player_Function.dnh" +#include "./Player_ShotConst.dnh" + +#include "script/KevinSystem/kevin_system/Kevin_ItemConst.txt" +#include "script/KevinSystem/kevin_system/Kevin_ItemLib.txt" + +let csd = GetCurrentScriptDirectory(); + + +// Global Variables + +float maxX = GetStgFrameWidth(); +float maxY = GetStgFrameHeight(); + +// Images & Sound + +let teamimg = csd ~ "./playerlib/Player_Sheet.png"; +LoadTextureEx(teamimg, true, true); +//ObjRender_SetTextureFilterMip(teamimg, FILTER_LINEAR); + +let plimg = csd ~ "./playerlib/PlSheet_Kouryuu.png"; +LoadTextureEx(plimg, true, true); +ObjRender_SetTextureFilter(plimg, FILTER_NONE, FILTER_NONE, FILTER_NONE); + +let sndpath = csd ~ "./sound"; + +int[] _enemyArray = []; +int[] _existArray = []; +int[] _shotArray = []; + +bool isChain = false; +bool isUseSpecialWpn = false; +float curChain = 0; + +// Other stuff + +float playerX = 0; +float playerY = 0; + +let objPlayer = GetPlayerObjectID(); +int plrender = 42; + +bool ripplayer = false; +float shotspeed = 0; +float bombrand = 0; + +int grazecounter = 0; // For basic graze = PIV mechanic + +int shotAlpha = (GetAreaCommonData("Config", "PlayerShotOpacity", 60)*0.01)*255; + +float shotDamageOption = 4.8; +float shotScaleOption = 1; + +float shotDamageLaser = 2; +float shotScaleLaser = 1; + +float shotDamageSpecial = 4.5; +float shotScaleSpecial = 2; + +float[] PlayerSpd = [15, 7.5]; + +// Custom events for scoring mechanic + +const EV_PIV_100 = EV_USER + 100i; // Normal enemies and nons +const EV_PIV_250 = EV_USER + 101i; // Spells +const EV_PIV_500 = EV_USER + 102i; // Last Spells +const EV_PIV_2000 = EV_USER + 103i; // What. + +@Initialize{ + + if(!IsCommonDataAreaExists("PIV")){ + CreateCommonDataArea("PIV"); + SetAreaCommonData("PIV", "currentvalue", 10000); + SetAreaCommonData("PIV", "ChainAmount", 1); + } + else{} + + SetPlayerStateEndEnable(true); + + // Stuff + Parameter(); + RenderPlayer(); + + UpdateAng(); + BaseShot(); + InitiateOptions(); + + Obj_SetRenderPriorityI(objPlayer, 43); + plrender = Obj_GetRenderPriorityI(objPlayer); + _SoundTask(); + + //SetIntersectionVisualization(true); // Debug + + _Mechanic(ripplayer, _enemyArray, _existArray, GetStgFrameWidth(), GetStgFrameHeight(), objPlayer, GetEnemyBossSceneObjectID(), 1, 2, 80); + + _ShowChain(); + _HandleChainGauge(); + + _HitboxRender(ripplayer, objPlayer, plimg, teamimg, 768, 192, 832, 256, 1536, 896, 2048, 1408, 0.5, 0.65); + SetShotAutoDeleteClip(256, 256, 256, 256); + + _Countdown(); + + // Shot data loading + LoadPlayerShotData(csd ~ "./Player_ShotData.dnh"); +} + +@MainLoop{ + _enemyArray = GetIntersectionRegistedEnemyID; + shotspeed += 1; // Managing the shot rate + //_shotArray = GetAllShotID(TARGET_PLAYER); + //UniversalAlphaHandle(_shotArray); + plrender = Obj_GetRenderPriorityI(objPlayer); + playerX = ObjMove_GetX(objPlayer); + playerY = ObjMove_GetY(objPlayer); + yield; +} + +@Event{ + alternative(GetEventType) + + // Delete effect + case(EV_DELETE_SHOT_PLAYER){ + + if(GetCommonDataPtr(EFFECTCUT_PTR, 0) >= 3){} + + else{ + + let graphic = GetEventArgument(2); + float[] position = GetEventArgument(1); + + let obj = CreatePlayerShotA1(position[0], position[1], 0, ObjMove_GetAngle(GetEventArgument(0)), 0, 99999, graphic); + + ObjShot_SetIntersectionEnable(obj, false); _DeleteEffect(obj, graphic == FIRE_SPECIAL ? 2 : 1); + + } + //if(graphic == ELECTRIC_FIRE_ALT) {_DeleteEffectAlt(obj);} + //else{_DeleteEffect(obj);} + } + + // PIV-item spawning events + case(EV_PIV_100){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_100, arg[0], arg[1]); + } + + case(EV_PIV_250){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_250, arg[0], arg[1]); + } + + case(EV_PIV_500){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_500, arg[0], arg[1]); + } + + // Basic functionality events + case(EV_REQUEST_SPELL){ + let bomb = GetPlayerSpell(); + + if (bomb >= 1){ + SetScriptResult(true); + SetPlayerSpell(bomb - 1); + _Bomb(); + SetCommonData("Rank", clamp(max(1, GetCommonData("Rank", 1)-0.25), GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); + _SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, GetPlayerInvincibilityFrame()); + } + + else { + SetScriptResult(false); + } + } + + case(EV_HIT){ + ObjSound_Play(PlayerHit); + _DeathbombWarning(plimg, [832, 0, 1088, 256], 20, 3); + } + + case(EV_CHAIN_MAX){ + + if(!isChain){ + ObjSound_Play(Shine); + isChain = true; + curChain = GetCommonDataPtr(POINTER_CHAIN, 1); + } + else{} + + } + + case(EV_CHAIN_RELEASE){ + + } + + case(EV_CHAIN_END){ + + SetAreaCommonData("PIV", "ChainAmount", 1); + isChain = false; + + // Increase rank depending on curChain (>= 32), then reset curChain. MAX CHAIN increases rank by 0.4. + + if(curChain >= 32){ + SetCommonData("Rank", clamp(GetCommonData("Rank", 1) + Interpolate_Linear(0.25, 0.5, curChain/64), GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); + } + + curChain = 1; + + } + + case(EV_PLAYER_SHOOTDOWN){ + ObjSound_Play(PlayerDie2); + SetPlayerSpell(GetPlayerSpell()+2); + ripplayer = true; + DeleteShotAll(TYPE_SHOT, TYPE_ITEM); + SetCommonData("Rank", clamp(GetCommonData("Rank", 1) * 0.75, GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); + _SigilCall(true, teamimg, 768, 512, 768+256, 768, objPlayer, 60); + } + + case(EV_PLAYER_REBIRTH){ + ripplayer = false; + SetPlayerInvincibilityFrame(180); + //_Countdown(); + _SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, 150); + + } + + case(EV_GRAZE){ + + } +} + +@Finalize{ + +} + + +// Basic player parameters + +task Parameter(){ + + // im trying to not be collected by the player but their item scope is dummy thicc and im alerted by its cheek + SetPlayerItemScope(360); + + SetPlayerLife(9); // Debug + SetPlayerSpell(2); + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); // (original: 5.25/2.0) + SetPlayerRebirthFrame(20); + SetPlayerDownStateFrame(60); + SetPlayerAutoItemCollectLine(GetStgFrameHeight/3); + SetPlayerRebirthLossFrame(0); + ObjPlayer_AddIntersectionCircleA1(objPlayer, 0, 0, 0, 40); + +} + +// Player render + +task RenderPlayer(){ + + // Why is this movement code so cursed jesus fucking christ + + float scale = 1; // Scalies + int frame = 0; + + ObjPrim_SetTexture(objPlayer, plimg); + ObjSprite2D_SetSourceRect(objPlayer, 0, 0, 128, 192); + ObjSprite2D_SetDestCenter(objPlayer); + Obj_SetRenderPriorityI(objPlayer, plrender); + //ObjRender_SetTextureFilterMin(objPlayer, FILTER_ANISOTROPIC); + ObjRender_SetScaleXYZ(objPlayer, scale, scale, 1); + + // Lower "speed" parameter = FASTER SPEED + + // FOR WHEN ONLY IDLE SPRITES ARE DONE + + loop{ + frame++; + _RenderPlayerMovement(objPlayer, frame, 0, 0, 128, 192, scale, 3, 6); + if (frame >= (3*6-1)){frame = 0;} + yield; + } + +} + +// Handling of bomb + +task _Bomb(){ + + // 180 frames + + // Preparation + + SetForbidPlayerShot(true); + SetForbidPlayerSpell(true); + SetPlayerInvincibilityFrame(180); + // Spell object + let manageObj = GetSpellManageObject(); // SPELL BEGINS + ObjSpell_Regist(manageObj); + + // Fully refills chain gauge for 120 frames + // Activates chain but not FUN MODE + + async{ + loop(90){ + SetCommonDataPtr(POINTER_CHAINCHECK, true); + SetCommonDataPtr(POINTER_CHAINGAUGE, 100); + yield; + } + } + + task CreateFireRing(x, y){ + + float startAng = rand(0, 360); + + ascent(i in 0..8){ + int slash = CreatePlayerShotA1(x, y, 35, startAng + i * 360/8, shotDamageSpecial/4, 64, FIRE_SPECIAL); + ObjShot_SetPenetrateShotEnable(slash, false); + ObjRender_SetColorHSV(slash, 180, 255, 255); + _BulletRescalePlayer(slash, shotScaleSpecial/1.75, true, 1); + ObjShot_SetSpellFactor(slash, true); + ObjShot_SetEraseShot(slash, true); + Obj_SetRenderPriorityI(slash, plrender-1); + //ObjRender_SetBlendType(slash, BLEND_ADD_ARGB); + Fade(slash); + } + + ObjSound_Play(Explosion2); + + } + + task Fade(int ID){ + + ObjRender_SetAlpha(ID, 255); + ObjMove_AddPatternA2(ID, 0, 36, NO_CHANGE, -36/15, 2, 0); + + wait(15); + + ascent(i in 0..15){ + ObjRender_SetAlpha(ID, Interpolate_Accelerate(255, 0, i/15)); + yield; + } + + Obj_Delete(ID); + + } + + float bombX = playerX; + + ascent(i in 0..18){ + CreateFireRing(rand(bombX - 96, bombX + 96), Interpolate_Linear(STG_HEIGHT+128, -128, i/18)); + wait(4); + } + + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); + SetForbidPlayerShot(false); + Obj_Delete(manageObj); // !!! IMPORTANT !!! + + wait(60); + SetForbidPlayerSpell(false); + +} diff --git a/script/player/Kouryuu/Player_ShotConst.dnh b/script/player/Kouryuu/Player_ShotConst.dnh new file mode 100644 index 0000000..db4d78a --- /dev/null +++ b/script/player/Kouryuu/Player_ShotConst.dnh @@ -0,0 +1,12 @@ +let current = GetCurrentScriptDirectory(); +let path = current ~ "Player_ShotData.dnh"; +LoadPlayerShotData(path); +// ----- + +const OPTION = 1; +const FIRE_OPTION = 2; +const FIRE_BASE = 3; +const FIRE_BASE_B = 4; +const FIRE_SPECIAL = 5; + + diff --git a/script/player/Kouryuu/Player_ShotData.dnh b/script/player/Kouryuu/Player_ShotData.dnh new file mode 100644 index 0000000..feff704 --- /dev/null +++ b/script/player/Kouryuu/Player_ShotData.dnh @@ -0,0 +1,60 @@ +shot_image = "./playerlib/PlSheet_Kouryuu.png" + +ShotData{ + id = 0 // Dummy + rect = (0,0,0,0) + render = ALPHA + alpha = 0 + collision = 32 +} + +// Option + +ShotData{ + id = 1 + rect = (0, 192, 128, 384) + render = ALPHA + alpha = 255 + fixed_angle = true + collision = 0 // Hitbox of arrows is not centered on the sprite +} + +// Fire + +ShotData{ + id = 2 + rect = (128, 192, 256, 384) + render = ALPHA + alpha = 255 + collision = 64 // Hitbox of arrows is not centered on the sprite +} + +// Laser + +ShotData{ + id = 3 + rect = (256, 192, 384, 384) + render = ALPHA + alpha = 255 + collision = 64 // Hitbox of arrows is not centered on the sprite +} + +// Laser 2 + +ShotData{ + id = 4 + rect = (384, 192, 512, 384) + render = ALPHA + alpha = 255 + collision = 64 // Hitbox of arrows is not centered on the sprite +} + +// Slash + +ShotData{ + id = 5 + rect = (512, 192, 640, 384) + render = ALPHA + alpha = 255 + collision = 64 // Hitbox of arrows is not centered on the sprite +} \ No newline at end of file diff --git a/script/player/Kouryuu/desc.txt b/script/player/Kouryuu/desc.txt new file mode 100644 index 0000000..e69de29 diff --git a/script/player/Kouryuu/playerlib/PlSheet_Kouryuu.png b/script/player/Kouryuu/playerlib/PlSheet_Kouryuu.png new file mode 100644 index 0000000..aaf447b Binary files /dev/null and b/script/player/Kouryuu/playerlib/PlSheet_Kouryuu.png differ diff --git a/script/player/Kouryuu/playerlib/RAW/KouryuuPalette.aseprite b/script/player/Kouryuu/playerlib/RAW/KouryuuPalette.aseprite new file mode 100644 index 0000000..903fad5 Binary files /dev/null and b/script/player/Kouryuu/playerlib/RAW/KouryuuPalette.aseprite differ diff --git a/script/player/Kouryuu/playerlib/RAW/soGay.aseprite b/script/player/Kouryuu/playerlib/RAW/soGay.aseprite new file mode 100644 index 0000000..373e908 Binary files /dev/null and b/script/player/Kouryuu/playerlib/RAW/soGay.aseprite differ diff --git a/script/player/Kouryuu/playerlib/RAW/soTrue.aseprite b/script/player/Kouryuu/playerlib/RAW/soTrue.aseprite new file mode 100644 index 0000000..c095ade Binary files /dev/null and b/script/player/Kouryuu/playerlib/RAW/soTrue.aseprite differ diff --git a/script/player/Kouryuu/sound/CK Music Factory/air01.wav b/script/player/Kouryuu/sound/CK Music Factory/air01.wav new file mode 100644 index 0000000..bc2c0ed Binary files /dev/null and b/script/player/Kouryuu/sound/CK Music Factory/air01.wav differ diff --git a/script/player/Kouryuu/sound/CK Music Factory/air02.wav b/script/player/Kouryuu/sound/CK Music Factory/air02.wav new file mode 100644 index 0000000..f7e5ed8 Binary files /dev/null and b/script/player/Kouryuu/sound/CK Music Factory/air02.wav differ diff --git a/script/player/Kouryuu/sound/CK Music Factory/laser01.wav b/script/player/Kouryuu/sound/CK Music Factory/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/Kouryuu/sound/CK Music Factory/laser01.wav differ diff --git a/script/player/Kouryuu/sound/CK Music Factory/slash01.wav b/script/player/Kouryuu/sound/CK Music Factory/slash01.wav new file mode 100644 index 0000000..364dfca Binary files /dev/null and b/script/player/Kouryuu/sound/CK Music Factory/slash01.wav differ diff --git a/script/player/Kouryuu/sound/CK Music Factory/wind01.wav b/script/player/Kouryuu/sound/CK Music Factory/wind01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/Kouryuu/sound/CK Music Factory/wind01.wav differ diff --git a/script/player/Kouryuu/sound/TAM Music Factory/se04.wav b/script/player/Kouryuu/sound/TAM Music Factory/se04.wav new file mode 100644 index 0000000..ca33890 Binary files /dev/null and b/script/player/Kouryuu/sound/TAM Music Factory/se04.wav differ diff --git a/script/player/Kouryuu/sound/TAM Music Factory/status4.wav b/script/player/Kouryuu/sound/TAM Music Factory/status4.wav new file mode 100644 index 0000000..1227a08 Binary files /dev/null and b/script/player/Kouryuu/sound/TAM Music Factory/status4.wav differ diff --git a/script/player/Kouryuu/sound/TAM Music Factory/tama2.wav b/script/player/Kouryuu/sound/TAM Music Factory/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/Kouryuu/sound/TAM Music Factory/tama2.wav differ diff --git a/script/player/Kouryuu/sound/bfxr_scythecall.wav b/script/player/Kouryuu/sound/bfxr_scythecall.wav new file mode 100644 index 0000000..99b3040 Binary files /dev/null and b/script/player/Kouryuu/sound/bfxr_scythecall.wav differ diff --git a/script/player/Kouryuu/sound/bfxr_splash.wav b/script/player/Kouryuu/sound/bfxr_splash.wav new file mode 100644 index 0000000..6a4d49d Binary files /dev/null and b/script/player/Kouryuu/sound/bfxr_splash.wav differ diff --git a/script/player/Kouryuu/sound/bfxr_teleporthigh.wav b/script/player/Kouryuu/sound/bfxr_teleporthigh.wav new file mode 100644 index 0000000..cc8b9ae --- /dev/null +++ b/script/player/Kouryuu/sound/bfxr_teleporthigh.wav @@ -0,0 +1 @@ +2,0.57,,0.3442,,0.2691,0.3,0.2179,,0.3445,,,,,,,,,,,0.2992,,0.5139,,,1,,,,,,,masterVolume \ No newline at end of file diff --git a/script/player/Kouryuu/sound/bfxr_teleportlow.wav b/script/player/Kouryuu/sound/bfxr_teleportlow.wav new file mode 100644 index 0000000..d55ce4b Binary files /dev/null and b/script/player/Kouryuu/sound/bfxr_teleportlow.wav differ diff --git a/script/player/Kouryuu/sound/bfxr_watershoot.wav b/script/player/Kouryuu/sound/bfxr_watershoot.wav new file mode 100644 index 0000000..6cfced3 Binary files /dev/null and b/script/player/Kouryuu/sound/bfxr_watershoot.wav differ diff --git a/script/player/Kouryuu/sound/birdcall05.wav b/script/player/Kouryuu/sound/birdcall05.wav new file mode 100644 index 0000000..ec6c7b9 Binary files /dev/null and b/script/player/Kouryuu/sound/birdcall05.wav differ diff --git a/script/player/Kouryuu/sound/hit01.wav b/script/player/Kouryuu/sound/hit01.wav new file mode 100644 index 0000000..0698a04 Binary files /dev/null and b/script/player/Kouryuu/sound/hit01.wav differ diff --git a/script/player/Kouryuu/sound/laser01.wav b/script/player/Kouryuu/sound/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/Kouryuu/sound/laser01.wav differ diff --git a/script/player/Kouryuu/sound/magic21.wav b/script/player/Kouryuu/sound/magic21.wav new file mode 100644 index 0000000..19714fe Binary files /dev/null and b/script/player/Kouryuu/sound/magic21.wav differ diff --git a/script/player/Kouryuu/sound/retrolaser.wav b/script/player/Kouryuu/sound/retrolaser.wav new file mode 100644 index 0000000..a58304e Binary files /dev/null and b/script/player/Kouryuu/sound/retrolaser.wav differ diff --git a/script/player/Kouryuu/sound/slash01.wav b/script/player/Kouryuu/sound/slash01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/Kouryuu/sound/slash01.wav differ diff --git a/script/player/Kouryuu/sound/tama2.wav b/script/player/Kouryuu/sound/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/Kouryuu/sound/tama2.wav differ diff --git a/script/player/Lavender/Player_Function.dnh b/script/player/Lavender/Player_Function.dnh new file mode 100644 index 0000000..aabda52 --- /dev/null +++ b/script/player/Lavender/Player_Function.dnh @@ -0,0 +1,299 @@ +// Shot Type + +int[] optionArr = []; +float angSpace = 2.5; + +float[] angStartArr = []; + +// Far left, left, right, far right + +float[] angStartUF = [230, 270, 270, 310]; +float[] angStartUFAlt = [230, 275, 265, 310]; +float[] angStartF = [250, 280, 260, 290]; + +float offsetX = 125; +float offsetY = 75; + +int[] bulletNum = [4, 3, 3, 4]; + + +task _HomeShot(int shot_) { + + float duration = 55; + bool homingBool = false; + float basepenetrate = ObjShot_GetPenetration(shot_); + float basedmg = ObjShot_GetDamage(shot_); + + // + + for (int t = 0i; t < duration && !Obj_IsDeleted(shot_); t++) { + + // Checks if enemies are on screen. If enemies are visible, enable homing for the shots. + // _enemyArray is an array containing all enemy IDs, and is constantly updated in @MainLoop. + + if (0 < length(_enemyArray)) { + float targetDist = 2000; // Arbitrary number (???) + int targetID = 0; + + // Checks distance of every enemy on screen. + + for each (int enemy in ref _enemyArray) { + float enemyX = ObjMove_GetX(enemy); + float enemyY = ObjMove_GetY(enemy); + if (0 < enemyX && enemyX < maxX && 0 < enemyY && enemyY < maxY) { + + // Returns the hypotenuse of the triangle formed by the x & y distances between the shot and the enemy. + + float shotDist = hypot(enemyX - ObjMove_GetX(shot_), enemyY - ObjMove_GetY(shot_)); + + // Locks the shot onto the enemy. + + if (shotDist < targetDist) { + targetDist = shotDist; + targetID = enemy; + homingBool = true; + } + } + } + + // Code to handle the actual homing. + + if (homingBool) { + for (int f = 0; t < duration && !Obj_IsDeleted(shot_) && !Obj_IsDeleted(targetID) && ObjEnemy_GetInfo(targetID, INFO_LIFE) != 0 && !ObjCol_IsIntersected(shot_); t++) { + ObjShot_SetAutoDelete(shot_, false); + float shotAngle = NormalizeAngle(ObjMove_GetAngle(shot_)); // Angle of the player shot + float targetAngle = NormalizeAngle(atan2(ObjMove_GetY(targetID) - ObjMove_GetY(shot_), ObjMove_GetX(targetID) - ObjMove_GetX(shot_))); // Returns angle from the shot to the enemy. + float angleDistance = AngularDistance(shotAngle, targetAngle); // Angular distance between enemy and player shot + float homeRate = Interpolate_Decelerate(0, 0.8, min(45, f) / 45); + // Homing speed? + ObjMove_SetAngle(shot_, Interpolate_Accelerate(shotAngle, shotAngle + angleDistance, homeRate)); // Interpolate_Necko + f++; + yield; + } + ObjShot_SetAutoDelete(shot_, true); + ObjMove_SetAngularVelocity(shot_, 0); + homingBool = false; + } + } + + yield; + } +} + +task UpdateAng(){ + while(true){ + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + angStartArr = angStartF; + angSpace = 9; + } + else{ + angStartArr = angStartUF; + angSpace = 18; + } + yield; + } +} + +task ShotType(){ + +} + +function CreateOption( + float offsetX_uf, offsetY_uf, + float offsetX_f, offsetY_f, + float ang_uf, ang_f +){ + +// Option + + int option = PlayerOption_LinearMove( + offsetX_uf, offsetY_uf, offsetX_f, offsetY_f, + true, ang_uf, ang_f, + plimg, + OPTION, 0.5, 39, + 128, 1, 1, false, + false, 1, + false, false + ); + + return option; + +} + +// CALL THIS TASK FIRST + +task InitiateOptions(){ + + // Far left, left, right, far right + + float[][] offsetArr = [ + [-offsetX * 1.5, offsetY * 1.25, -offsetX * 1, offsetY * 0.75], + [-offsetX * 1, 0, -offsetX * 0.75, -offsetY * 0.4], + [offsetX * 1, 0, offsetX * 0.75, -offsetY * 0.4], + [offsetX * 1.5, offsetY * 1.25, offsetX * 1, offsetY * 0.75], + ]; + + int count = 0; + + for each (float[] entry in ref offsetArr){ + + int option = CreateOption( + offsetArr[count][0], offsetArr[count][1], + offsetArr[count][2], offsetArr[count][3], + angStartUF[count], angStartF[count] + ); + optionArr = optionArr ~ [option]; + ShotType(option, angStartUFAlt[count], angStartF[count], bulletNum[count]); + SpecialWeapon(option, angStartUFAlt[count], angStartF[count], bulletNum[count]); + count++; + + } +} + + +task BaseShot(){ + + int angMultiplier = 0; + + while(true){ + + if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && GetVirtualKeyState(VK_USER1) == KEY_FREE &&IsPermitPlayerShot && !ripplayer){ + + if(shotspeed % 4 == 0){ + + ObjSound_Play(Base3); + + let shotA = CreatePlayerShotA1(playerX, playerY, 52, 270, shotDamage*2, 1.2, FIRE_BASE); + _BulletRescalePlayer(shotA, shotScale1, true, 1); + ObjRender_SetAlpha(shotA, shotAlpha); + Obj_SetRenderPriorityI(shotA, 41); + + } + + } + + yield; + + } + +} + +task ShotType(int ID, float startAngUF, startAngF, int bulletNum){ + + int angMultiplier = 0; + + while(true){ + if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && GetVirtualKeyState(VK_USER1) == KEY_FREE &&IsPermitPlayerShot && !ripplayer){ + + if(shotspeed % 3*(bulletNum+1) == 0){ + + float x = ObjMove_GetX(ID); + float y = ObjMove_GetY(ID); + + int multiplier = 1; + + if(x-playerX > 0){multiplier = 1;} + else{multiplier = -1;} + + //ObjSound_Play(Base3); + + loop(bulletNum){ + + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + + let shotA = CreatePlayerShotA1(x, y, 45, startAngF+angSpace*multiplier*angMultiplier, shotDamage, 1.1, FIRE_NORMAL); + _BulletRescalePlayer(shotA, shotScale1, true, 1); + ObjRender_SetAlpha(shotA, shotAlpha); + Obj_SetRenderPriorityI(shotA, 41); + + } + + else{ + + let shotA = CreatePlayerShotA1(x, y, 45, startAngUF+angSpace*multiplier*angMultiplier, shotDamage, 1.1, FIRE_NORMAL); + _BulletRescalePlayer(shotA, shotScale1, true, 1); + ObjRender_SetAlpha(shotA, shotAlpha); + Obj_SetRenderPriorityI(shotA, 41); + + } + + angMultiplier ++; + + wait(2); + + } + + angMultiplier = 0; + + } + + } + yield; + } + + +} + +task SpecialWeapon(int ID, float startAngUF, startAngF, int bulletNum){ + + int angMultiplier = 0; + + while(true){ + + if(GetVirtualKeyState(VK_USER1) != KEY_FREE && GetCommonDataPtr(POINTER_SPECIALAMMO, 100) > 0 && IsPermitPlayerShot && !ripplayer){ + + SetCommonDataPtr(POINTER_SPECIALCHECK, true); + SetCommonDataPtr(POINTER_CHAINCHECK, true); + + // 15 ammo per second + + if(shotspeed % 4 == 0){ + + float x = ObjMove_GetX(ID); + float y = ObjMove_GetY(ID); + + SetCommonDataPtr(POINTER_SPECIALAMMO, max(0, GetCommonDataPtr(POINTER_SPECIALAMMO, 100)-(15/60))); + + // Minimal rank boost -> +0.5 rank for every 10 seconds of the wpn being used -> 1/20 rank every sec -> 1/300 rank every 4 frames + + SetCommonData("Rank", clamp(GetCommonData("Rank", 1) + 1/(300*4), GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); + + int multiplier = 1; + + if(x-playerX > 0){multiplier = 1;} + else{multiplier = -1;} + + ObjSound_Play(Base2); + + loop(1){ + + let shotA = CreatePlayerShotA1(x, y, 45, startAngF+rand(-1, 1), shotDamageSpecial, 1.1, FIRE_SPECIAL); + _BulletRescalePlayer(shotA, shotScale1*2, true, 1); + _HomeShot(shotA); + ObjRender_SetAlpha(shotA, shotAlpha); + Obj_SetRenderPriorityI(shotA, 41); + + angMultiplier ++; + + } + + angMultiplier = 0; + + } + + } + + else{ + + SetCommonDataPtr(POINTER_CHAINCHECK, false); + if(GetCommonDataPtr(POINTER_CHAINGAUGE, 0) <= 0){SetCommonDataPtr(POINTER_SPECIALCHECK, false);} + + } + + yield; + } + +} + +// Bomb +// Yassbong explosion \ No newline at end of file diff --git a/script/player/Lavender/Player_Main.dnh b/script/player/Lavender/Player_Main.dnh new file mode 100644 index 0000000..7306dbe --- /dev/null +++ b/script/player/Lavender/Player_Main.dnh @@ -0,0 +1,364 @@ +#TouhouDanmakufu[Player] +#ScriptVersion[3] +#ID["PL1_LAVENDER"] +#Title["Lavender Mushihime"] +#Text["Player 1"] + +//#Image["./mariremi_lib/mariremi_illust.png"] + +#ReplayName["Lavender"] + +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" + +#include "script/KevinSystem/Kevin_PlayerLib.txt" +#include "script/KevinSystem/PlayerSoundLib.dnh" + +#include "./Player_Function.dnh" +#include "./Player_ShotConst.dnh" + +#include "script/KevinSystem/kevin_system/Kevin_ItemConst.txt" +#include "script/KevinSystem/kevin_system/Kevin_ItemLib.txt" + +let csd = GetCurrentScriptDirectory(); + + +// Global Variables + +float maxX = GetStgFrameWidth(); +float maxY = GetStgFrameHeight(); + +// Images & Sound + +let teamimg = csd ~ "./playerlib/Player_Sheet.png"; +LoadTextureEx(teamimg, true, true); +//ObjRender_SetTextureFilterMip(teamimg, FILTER_LINEAR); + +let plimg = csd ~ "./playerlib/PlSheet_Lavender.png"; +LoadTextureEx(plimg, true, true); +ObjRender_SetTextureFilter(plimg, FILTER_NONE, FILTER_NONE, FILTER_NONE); + +let sndpath = csd ~ "./sound"; + +int[] _enemyArray = []; +int[] _existArray = []; +int[] _shotArray = []; + +bool isChain = false; +bool isUseSpecialWpn = false; +float curChain = 0; + +// Other stuff + +float playerX = 0; +float playerY = 0; + +let objPlayer = GetPlayerObjectID(); +int plrender = Obj_GetRenderPriorityI(objPlayer); + +bool ripplayer = false; +float shotspeed = 0; +float bombrand = 0; + +int grazecounter = 0; // For basic graze = PIV mechanic + +int shotAlpha = (GetAreaCommonData("Config", "PlayerShotOpacity", 60)*0.01)*255; +float shotDamage = 3.1; +float shotDamageSpecial = 6.25; +float shotScale1 = 1; + +float[] PlayerSpd = [13, 6.5]; + +// Custom events for scoring mechanic + +const EV_PIV_100 = EV_USER + 100i; // Normal enemies and nons +const EV_PIV_250 = EV_USER + 101i; // Spells +const EV_PIV_500 = EV_USER + 102i; // Last Spells +const EV_PIV_2000 = EV_USER + 103i; // What. + +@Initialize{ + + if(!IsCommonDataAreaExists("PIV")){ + CreateCommonDataArea("PIV"); + SetAreaCommonData("PIV", "currentvalue", 10000); + SetAreaCommonData("PIV", "ChainAmount", 1); + } + else{} + + SetPlayerStateEndEnable(true); + + // Stuff + Parameter(); + RenderPlayer(); + + UpdateAng(); + BaseShot(); + InitiateOptions(); + + Obj_SetRenderPriorityI(objPlayer, 43); + plrender = Obj_GetRenderPriorityI(objPlayer); + _SoundTask(); + + //SetIntersectionVisualization(true); // Debug + + _Mechanic(ripplayer, _enemyArray, _existArray, GetStgFrameWidth(), GetStgFrameHeight(), objPlayer, GetEnemyBossSceneObjectID(), 1, 2, 80); + + _ShowChain(); + _HandleChainGauge(); + + _HitboxRender(ripplayer, objPlayer, plimg, teamimg, 768, 192, 832, 256, 1536, 896, 2048, 1408, 0.5, 0.65); + SetShotAutoDeleteClip(256, 256, 256, 256); + + _Countdown(); + + // Shot data loading + LoadPlayerShotData(csd ~ "./Player_ShotData.dnh"); +} + +@MainLoop{ + _enemyArray = GetIntersectionRegistedEnemyID; + shotspeed += 1; // Managing the shot rate + //_shotArray = GetAllShotID(TARGET_PLAYER); + //UniversalAlphaHandle(_shotArray); + playerX = ObjMove_GetX(objPlayer); + playerY = ObjMove_GetY(objPlayer); + yield; +} + +@Event{ + alternative(GetEventType) + + // Delete effect + case(EV_DELETE_SHOT_PLAYER){ + + if(GetCommonDataPtr(EFFECTCUT_PTR, 0) >= 3){} + + else{ + let graphic = GetEventArgument(2); + float[] position = GetEventArgument(1); + let obj = CreatePlayerShotA1(position[0], position[1], 0, ObjMove_GetAngle(GetEventArgument(0)), 0, 99999, graphic); + ObjShot_SetIntersectionEnable(obj, false); _DeleteEffect(obj, graphic == FIRE_SPECIAL ? shotScale1 * 2 : shotScale1); + } + //if(graphic == ELECTRIC_FIRE_ALT) {_DeleteEffectAlt(obj);} + //else{_DeleteEffect(obj);} + } + + // PIV-item spawning events + case(EV_PIV_100){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_100, arg[0], arg[1]); + } + + case(EV_PIV_250){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_250, arg[0], arg[1]); + } + + case(EV_PIV_500){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_500, arg[0], arg[1]); + } + + // Basic functionality events + case(EV_REQUEST_SPELL){ + let bomb = GetPlayerSpell(); + + if (bomb >= 1){ + SetScriptResult(true); + SetPlayerSpell(bomb - 1); + _Bomb(); + SetCommonData("Rank", clamp(max(1, GetCommonData("Rank", 1)-0.25), GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); + + _SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, GetPlayerInvincibilityFrame()); + } + + else { + SetScriptResult(false); + } + } + + case(EV_HIT){ + ObjSound_Play(PlayerHit); + _DeathbombWarning(plimg, [832, 0, 1088, 256], 20, 3); + } + + case(EV_CHAIN_MAX){ + + if(!isChain){ + ObjSound_Play(Shine); + isChain = true; + curChain = GetCommonDataPtr(POINTER_CHAIN, 1); + } + else{} + + } + + case(EV_CHAIN_RELEASE){ + + } + + case(EV_CHAIN_END){ + + SetAreaCommonData("PIV", "ChainAmount", 1); + isChain = false; + + // Increase rank depending on curChain (>= 32), then reset curChain. MAX CHAIN increases rank by 0.4. + + if(curChain >= 32){ + SetCommonData("Rank", clamp(GetCommonData("Rank", 1) + Interpolate_Linear(0.25, 0.5, curChain/64), GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); + } + + curChain = 1; + + } + + case(EV_PLAYER_SHOOTDOWN){ + ObjSound_Play(PlayerDie2); + SetPlayerSpell(GetPlayerSpell()+2); + ripplayer = true; + DeleteShotAll(TYPE_SHOT, TYPE_ITEM); + + // Decrease rank by 1/4 + + SetCommonData("Rank", clamp(GetCommonData("Rank", 1) * 0.75, GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); + + _SigilCall(true, teamimg, 768, 512, 768+256, 768, objPlayer, 60); + } + + case(EV_PLAYER_REBIRTH){ + ripplayer = false; + SetPlayerInvincibilityFrame(180); + //_Countdown(); + _SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, 150); + + } + + case(EV_GRAZE){ + + } +} + +@Finalize{ + +} + + +// Basic player parameters + +task Parameter(){ + + // im trying to not be collected by the player but their item scope is dummy thicc and im alerted by its cheek + SetPlayerItemScope(360); + + SetPlayerLife(9); // Debug + SetPlayerSpell(2); + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); // (original: 5.25/2.0) + SetPlayerRebirthFrame(20); + SetPlayerDownStateFrame(60); + SetPlayerAutoItemCollectLine(GetStgFrameHeight/3); + SetPlayerRebirthLossFrame(0); + ObjPlayer_AddIntersectionCircleA1(objPlayer, 0, 0, 0, 40); + +} + +// Player render + +task RenderPlayer(){ + + // Why is this movement code so cursed jesus fucking christ + + float scale = 1; // Scalies + int frame = 0; + + ObjPrim_SetTexture(objPlayer, plimg); + ObjSprite2D_SetSourceRect(objPlayer, 0, 0, 128, 192); + ObjSprite2D_SetDestCenter(objPlayer); + Obj_SetRenderPriorityI(objPlayer, 42); + //ObjRender_SetTextureFilterMin(objPlayer, FILTER_ANISOTROPIC); + ObjRender_SetScaleXYZ(objPlayer, scale, scale, 1); + + // Lower "speed" parameter = FASTER SPEED + + loop{ + frame++; + _RenderPlayerMovement(objPlayer, frame, 0, 0, 128, 192, scale, 3, 6); + if (frame >= (3*6-1)){frame = 0;} + yield; + } + +} + +// Handling of bomb + +task _Bomb(){ + + // Fire rings explode in a straight line, bomb lasts 90 frames with 240-frame total invincibility + + // Preparation + + SetForbidPlayerShot(true); + SetForbidPlayerSpell(true); + SetPlayerInvincibilityFrame(120); + // Spell object + let manageObj = GetSpellManageObject(); // SPELL BEGINS + ObjSpell_Regist(manageObj); + + // Fully refills chain gauge for 120 frames + // Activates chain but not FUN MODE + + async{ + loop(60){ + SetCommonDataPtr(POINTER_CHAINCHECK, true); + SetCommonDataPtr(POINTER_CHAINGAUGE, 100); + yield; + } + } + + task CreateFireRing(x, y){ + + float startAng = rand(0, 360); + + ascent(i in 0..16){ + int slash = CreatePlayerShotA1(x, y, 35, startAng + i * 360/16, shotDamageSpecial/8, 64, FIRE_SPECIAL); + ObjShot_SetPenetrateShotEnable(slash, false); + ObjRender_SetColorHSV(slash, 180, 255, 255); + _BulletRescalePlayer(slash, shotScale1*2.5, true, 1); + ObjShot_SetSpellFactor(slash, true); + ObjShot_SetEraseShot(slash, true); + Obj_SetRenderPriorityI(slash, plrender-1); + //ObjRender_SetBlendType(slash, BLEND_ADD_ARGB); + Fade(slash); + } + + ObjSound_Play(Explosion2); + + } + + task Fade(int ID){ + + ObjRender_SetAlpha(ID, 255); + ObjMove_AddPatternA2(ID, 0, 40, NO_CHANGE, -40/25, 15, 0); + + ascent(i in 0..15){ + ObjRender_SetAlpha(ID, Interpolate_Accelerate(255, 0, i/15)); + yield; + } + + Obj_Delete(ID); + + } + + float bombX = playerX; + + ascent(i in 0..15){ + CreateFireRing(rand(0, STG_WIDTH), rand(0, STG_HEIGHT)); + wait(4); + } + + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); + SetForbidPlayerShot(false); + Obj_Delete(manageObj); // !!! IMPORTANT !!! + + wait(60); + SetForbidPlayerSpell(false); + +} diff --git a/script/player/Lavender/Player_ShotConst.dnh b/script/player/Lavender/Player_ShotConst.dnh new file mode 100644 index 0000000..63633a3 --- /dev/null +++ b/script/player/Lavender/Player_ShotConst.dnh @@ -0,0 +1,11 @@ +let current = GetCurrentScriptDirectory(); +let path = current ~ "Player_ShotData.dnh"; +LoadPlayerShotData(path); +// ----- + +const OPTION = 1; +const FIRE_NORMAL = 2; +const FIRE_SPECIAL = 3; +const FIRE_BASE = 4; + + diff --git a/script/player/Lavender/Player_ShotData.dnh b/script/player/Lavender/Player_ShotData.dnh new file mode 100644 index 0000000..afbdc64 --- /dev/null +++ b/script/player/Lavender/Player_ShotData.dnh @@ -0,0 +1,49 @@ +shot_image = "./playerlib/PlSheet_Lavender.png" + +ShotData{ + id = 0 // Dummy + rect = (0,0,0,0) + render = ALPHA + alpha = 0 + collision = 32 +} + +// Option + +ShotData{ + id = 1 + rect = (0, 192, 128, 384) + render = ALPHA + alpha = 255 + collision = 0 // Hitbox of arrows is not centered on the sprite +} + +// Fire1 + +ShotData{ + id = 2 + rect = (128, 192, 256, 384) + render = ALPHA + alpha = 255 + collision = 64 // Hitbox of arrows is not centered on the sprite +} + +// Fire2 + +ShotData{ + id = 3 + rect = (512, 192, 640, 384) + render = ALPHA + alpha = 255 + collision = 64 // Hitbox of arrows is not centered on the sprite +} + +// Fire0 + +ShotData{ + id = 4 + rect = (384, 192, 512, 384) + render = ALPHA + alpha = 255 + collision = 64 // Hitbox of arrows is not centered on the sprite +} \ No newline at end of file diff --git a/script/player/Lavender/desc.txt b/script/player/Lavender/desc.txt new file mode 100644 index 0000000..e69de29 diff --git a/script/player/Lavender/playerlib/PlSheet_Lavender.png b/script/player/Lavender/playerlib/PlSheet_Lavender.png new file mode 100644 index 0000000..03fd528 Binary files /dev/null and b/script/player/Lavender/playerlib/PlSheet_Lavender.png differ diff --git a/script/player/Lavender/playerlib/RAW/LavenderPalette.aseprite b/script/player/Lavender/playerlib/RAW/LavenderPalette.aseprite new file mode 100644 index 0000000..03adc15 Binary files /dev/null and b/script/player/Lavender/playerlib/RAW/LavenderPalette.aseprite differ diff --git a/script/player/Lavender/playerlib/RAW/soTrue.aseprite b/script/player/Lavender/playerlib/RAW/soTrue.aseprite new file mode 100644 index 0000000..c095ade Binary files /dev/null and b/script/player/Lavender/playerlib/RAW/soTrue.aseprite differ diff --git a/script/player/Lavender/sound/CK Music Factory/air01.wav b/script/player/Lavender/sound/CK Music Factory/air01.wav new file mode 100644 index 0000000..bc2c0ed Binary files /dev/null and b/script/player/Lavender/sound/CK Music Factory/air01.wav differ diff --git a/script/player/Lavender/sound/CK Music Factory/air02.wav b/script/player/Lavender/sound/CK Music Factory/air02.wav new file mode 100644 index 0000000..f7e5ed8 Binary files /dev/null and b/script/player/Lavender/sound/CK Music Factory/air02.wav differ diff --git a/script/player/Lavender/sound/CK Music Factory/laser01.wav b/script/player/Lavender/sound/CK Music Factory/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/Lavender/sound/CK Music Factory/laser01.wav differ diff --git a/script/player/Lavender/sound/CK Music Factory/slash01.wav b/script/player/Lavender/sound/CK Music Factory/slash01.wav new file mode 100644 index 0000000..364dfca Binary files /dev/null and b/script/player/Lavender/sound/CK Music Factory/slash01.wav differ diff --git a/script/player/Lavender/sound/CK Music Factory/wind01.wav b/script/player/Lavender/sound/CK Music Factory/wind01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/Lavender/sound/CK Music Factory/wind01.wav differ diff --git a/script/player/Lavender/sound/TAM Music Factory/se04.wav b/script/player/Lavender/sound/TAM Music Factory/se04.wav new file mode 100644 index 0000000..ca33890 Binary files /dev/null and b/script/player/Lavender/sound/TAM Music Factory/se04.wav differ diff --git a/script/player/Lavender/sound/TAM Music Factory/status4.wav b/script/player/Lavender/sound/TAM Music Factory/status4.wav new file mode 100644 index 0000000..1227a08 Binary files /dev/null and b/script/player/Lavender/sound/TAM Music Factory/status4.wav differ diff --git a/script/player/Lavender/sound/TAM Music Factory/tama2.wav b/script/player/Lavender/sound/TAM Music Factory/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/Lavender/sound/TAM Music Factory/tama2.wav differ diff --git a/script/player/Lavender/sound/bfxr_scythecall.wav b/script/player/Lavender/sound/bfxr_scythecall.wav new file mode 100644 index 0000000..99b3040 Binary files /dev/null and b/script/player/Lavender/sound/bfxr_scythecall.wav differ diff --git a/script/player/Lavender/sound/bfxr_splash.wav b/script/player/Lavender/sound/bfxr_splash.wav new file mode 100644 index 0000000..6a4d49d Binary files /dev/null and b/script/player/Lavender/sound/bfxr_splash.wav differ diff --git a/script/player/Lavender/sound/bfxr_teleporthigh.wav b/script/player/Lavender/sound/bfxr_teleporthigh.wav new file mode 100644 index 0000000..cc8b9ae --- /dev/null +++ b/script/player/Lavender/sound/bfxr_teleporthigh.wav @@ -0,0 +1 @@ +2,0.57,,0.3442,,0.2691,0.3,0.2179,,0.3445,,,,,,,,,,,0.2992,,0.5139,,,1,,,,,,,masterVolume \ No newline at end of file diff --git a/script/player/Lavender/sound/bfxr_teleportlow.wav b/script/player/Lavender/sound/bfxr_teleportlow.wav new file mode 100644 index 0000000..d55ce4b Binary files /dev/null and b/script/player/Lavender/sound/bfxr_teleportlow.wav differ diff --git a/script/player/Lavender/sound/bfxr_watershoot.wav b/script/player/Lavender/sound/bfxr_watershoot.wav new file mode 100644 index 0000000..6cfced3 Binary files /dev/null and b/script/player/Lavender/sound/bfxr_watershoot.wav differ diff --git a/script/player/Lavender/sound/birdcall05.wav b/script/player/Lavender/sound/birdcall05.wav new file mode 100644 index 0000000..ec6c7b9 Binary files /dev/null and b/script/player/Lavender/sound/birdcall05.wav differ diff --git a/script/player/Lavender/sound/hit01.wav b/script/player/Lavender/sound/hit01.wav new file mode 100644 index 0000000..0698a04 Binary files /dev/null and b/script/player/Lavender/sound/hit01.wav differ diff --git a/script/player/Lavender/sound/laser01.wav b/script/player/Lavender/sound/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/Lavender/sound/laser01.wav differ diff --git a/script/player/Lavender/sound/magic21.wav b/script/player/Lavender/sound/magic21.wav new file mode 100644 index 0000000..19714fe Binary files /dev/null and b/script/player/Lavender/sound/magic21.wav differ diff --git a/script/player/Lavender/sound/retrolaser.wav b/script/player/Lavender/sound/retrolaser.wav new file mode 100644 index 0000000..a58304e Binary files /dev/null and b/script/player/Lavender/sound/retrolaser.wav differ diff --git a/script/player/Lavender/sound/slash01.wav b/script/player/Lavender/sound/slash01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/Lavender/sound/slash01.wav differ diff --git a/script/player/Lavender/sound/tama2.wav b/script/player/Lavender/sound/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/Lavender/sound/tama2.wav differ diff --git a/script/player/Narumi/Player_Function.dnh b/script/player/Narumi/Player_Function.dnh new file mode 100644 index 0000000..80da165 --- /dev/null +++ b/script/player/Narumi/Player_Function.dnh @@ -0,0 +1,245 @@ +#include "./Player_Function_Laser.dnh" + +// Shot Type + +int[] optionArr = []; +float angSpace = 2.5; + +float[] angStartArr = []; + +// Far left, left, right, far right + +float[] angStartUF = [230, 270, 270, 310]; +float[] angStartUFAlt = [230, 275, 265, 310]; +float[] angStartF = [250, 280, 260, 290]; + +float offsetX = 125; +float offsetY = 75; + +int[] bulletNum = [4, 3, 3, 4]; + +task ShotType(){ +} + +task BaseShot(){ + + // 5 way shot + float[] angDist = [10, 5]; + float ang = -7.5; + float ang2 = -22.5; + + while(true){ + + if(GetVirtualKeyState(VK_SPELL) == KEY_FREE && IsPermitPlayerShot && !ripplayer){ + + // C for alt shot + if(GetVirtualKeyState(VK_USER1) != KEY_FREE){ + + if(shotspeed % 4 == 0){ + + ObjSound_Play(Base3); + + ascent(i in 0..3){ + + let shotA = CreatePlayerShotA1(playerX, playerY, 52, ang2 - ang2 * (i * 1), shotDamageOption, 1.5, AMULET); + _BulletRescalePlayer(shotA, shotScaleOption, true, 1); + ObjRender_SetAlpha(shotA, shotAlpha); + Obj_SetRenderPriorityI(shotA, 41); + + } + + ascent(i in 0..3){ + + let shotB = CreatePlayerShotA1(playerX, playerY, 52, ang2 - ang2 * (i * 1) + 180, shotDamageOption, 1.5, AMULET); + _BulletRescalePlayer(shotB, shotScaleOption, true, 1); + ObjRender_SetAlpha(shotB, shotAlpha); + Obj_SetRenderPriorityI(shotB, 41); + + } + + } + + } + + // Z/Z+C for normal shot + + else if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && GetVirtualKeyState(VK_USER1) == KEY_FREE){ + + if(shotspeed % 4 == 0){ + + ObjSound_Play(Base3); + + ascent(b in -2..3){ + + let shotC = CreatePlayerShotA1(playerX, playerY, 52, 0 + ang * b, shotDamageOption, 1.5, AMULET); + _BulletRescalePlayer(shotC, shotScaleOption, true, 1); + ObjRender_SetAlpha(shotC, shotAlpha); + Obj_SetRenderPriorityI(shotC, 41); + + } + + } + + } + + else{} + + } + + yield; + + } + +} + +task SpecialWeapon(){ + + // Create projectile, but disable hitbox & visibility + + int golem = CreatePlayerShotA1(playerX+128, playerY, 0, 0, shotDamageSpecial * 5.25, 999999, GOLEM); + ObjShot_SetAutoDelete(golem, false); + ObjShot_SetEraseShot(golem, true); + ObjShot_SetPenetrateShotEnable(golem, true); + ObjShot_SetIntersectionEnable(golem, false); + Obj_SetVisible(golem, false); + ObjRender_SetAlpha(golem, 0); + ObjShot_SetSpellFactor(golem, true); + _BulletRescalePlayer(golem, 1.5, true, 1); + ObjShot_SetSpinAngularVelocity(golem, 6); + + float i = 0; + + while(true){ + + if(GetVirtualKeyState(VK_SPELL) != KEY_FREE && GetCommonDataPtr(POINTER_SPECIALAMMO, 100) > 0 && !ripplayer){ + + if(shotspeed % 4 == 0){ObjSound_Play(Fire);} + + i = min(210, i+210/10); + ObjMove_SetPosition(golem, playerX + i, playerY); + ObjRender_SetAlpha(golem, min(255, ObjRender_GetAlpha(golem)+255/10)); + + //SetCommonDataPtr(POINTER_SPECIALCHECK, true); + SetCommonDataPtr(POINTER_CHAINCHECK, true); + SetPlayerSpeed(PlayerSpd[0]*1.5, PlayerSpd[1]*1.5); + // (Approx.) 20 ammo per second + + SetCommonDataPtr(POINTER_SPECIALAMMO, max(0, GetCommonDataPtr(POINTER_SPECIALAMMO, 100)-(20/60))); + ObjShot_SetIntersectionEnable(golem, true); + Obj_SetVisible(golem, true); + + // +1 rank per 10 seconds of use + + SetCommonData("Rank", clamp(GetCommonData("Rank", 1)+1/600, 1, GetCommonData("MaxRank", 6))); + + /* + if(shotspeed % 4 == 0){ + + float x = ObjMove_GetX(ID); + float y = ObjMove_GetY(ID); + + // Minimal rank boost -> +0.5 rank for every 10 seconds of the wpn being used -> 1/20 rank every sec -> 1/300 rank every 4 frames + + SetCommonData("Rank", clamp(GetCommonData("Rank", 1) + 1/300, GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); + + angFire[0] = 270 + angFlux * sin(ang1) + rand(-5, 5); + angFire[1] = 270 + angFlux * sin(ang2) + rand(-5, 5); + // YASS FIRE THOSE BITCH KILLER SLASHES + FireSlash(angFire[0], 50, 35, 45); + FireSlash(angFire[1], 50, 35, 45); + + ang1 += 25; + ang2 -= 25; + + } + */ + + } + + else{ + + // Refills 5 ammo per second + + i = max(0, i-210/10); + ObjMove_SetPosition(golem, playerX + i, playerY); + ObjRender_SetAlpha(golem, max(0, ObjRender_GetAlpha(golem)-255/10)); + + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); + SetCommonDataPtr(POINTER_SPECIALAMMO, min(100, GetCommonDataPtr(POINTER_SPECIALAMMO, 100)+(5/60))); + SetCommonDataPtr(POINTER_CHAINCHECK, false); + ObjShot_SetIntersectionEnable(golem, false); + + //if(GetCommonDataPtr(POINTER_CHAINGAUGE, 0) <= 0){SetCommonDataPtr(POINTER_SPECIALCHECK, false);} + + } + + yield; + } + +} + +task FireSlash( + float angle, baseSpd, + int decelTime, lifeTime +){ + + int slash = CreatePlayerShotA1(playerX, playerY, baseSpd, angle, shotDamageSpecial, 8, 1); + ObjShot_SetPenetrateShotEnable(slash, false); + _BulletRescalePlayer(slash, shotScaleSpecial, true, 1); + + Obj_SetRenderPriorityI(slash, plrender-1); + + //ObjRender_SetBlendType(slash, BLEND_ADD_ARGB); + ObjSound_Play(Base5); + ObjShot_SetEraseShot(slash, true); + + async{ + + ascent(i in 0..3){ + int slashA = CreatePlayerShotA1(playerX, playerY, baseSpd, angle, shotDamageSpecial/5, 32, 1); + _BulletRescalePlayer(slashA, shotScaleSpecial/2, true, 1); + //ObjRender_SetBlendType(slashA, BLEND_ADD_ARGB); + ObjShot_SetPenetrateShotEnable(slashA, false); + Obj_SetRenderPriorityI(slashA, plrender-1); + Fade(slashA); + wait(10); + } + + } + + task Fade(int ID){ + + ObjMove_AddPatternA2(ID, 0, baseSpd/2, [rand(180, 230), rand(-50, 30)][rand_int(0, 1)], (-baseSpd/2)/(decelTime), 2, 0); + + ascent(i in 0..(decelTime)){ + ObjRender_SetAlpha(ID, Interpolate_Accelerate(shotAlpha, 0, i/(decelTime))); + yield; + } + + Obj_Delete(ID); + + } + + async{ + + ObjMove_SetAcceleration(slash, -baseSpd/decelTime); + ObjMove_SetMaxSpeed(slash, baseSpd/50); + ObjRender_SetAlpha(slash, shotAlpha); + + ascent(i in 0..decelTime){ + ObjRender_SetScaleXYZ(slash, Interpolate_Accelerate(shotScaleSpecial/1.25, shotScaleSpecial, i/decelTime)); + yield; + } + + ascent(i in 0..(lifeTime-decelTime)){ + ObjRender_SetAlpha(slash, Interpolate_Accelerate(shotAlpha, 0, i/(lifeTime-decelTime))); + yield; + } + + Obj_Delete(slash); + + } +} + +// Bomb +// Holy fuck its literally YoumuA IBP \ No newline at end of file diff --git a/script/player/Narumi/Player_Function_Laser.dnh b/script/player/Narumi/Player_Function_Laser.dnh new file mode 100644 index 0000000..8d55f67 --- /dev/null +++ b/script/player/Narumi/Player_Function_Laser.dnh @@ -0,0 +1,232 @@ + +// Particle list for laser effect + +int LaserEffect = ObjParticleList_Create(OBJ_PARTICLE_LIST_2D); +int[] rect = [704, 192, 768, 256]; + +ObjPrim_SetTexture(LaserEffect, "script/player/Kouryuu/playerlib/PlSheet_Kouryuu.png"); + +Obj_SetRenderPriorityI(LaserEffect, 41); +ObjPrim_SetPrimitiveType(LaserEffect, PRIMITIVE_TRIANGLELIST); +ObjPrim_SetVertexCount(LaserEffect, 4); + +ObjRender_SetBlendType(LaserEffect, BLEND_ADD_ARGB); + +// Left-top, right-top, left-bottom, right-bottom + +ObjPrim_SetVertexUVT(LaserEffect, 0, rect[0], rect[1]); +ObjPrim_SetVertexUVT(LaserEffect, 1, rect[2], rect[1]); +ObjPrim_SetVertexUVT(LaserEffect, 2, rect[0], rect[3]); +ObjPrim_SetVertexUVT(LaserEffect, 3, rect[2], rect[3]); + +// Vertex positions are offset with deltas so that the sprite is centered + +float dU = (rect[2] - rect[0])/2; +float dV = (rect[3] - rect[1])/2; + +ObjPrim_SetVertexPosition(LaserEffect, 0, -dU, -dV, 1); +ObjPrim_SetVertexPosition(LaserEffect, 1, dU, -dV, 1); +ObjPrim_SetVertexPosition(LaserEffect, 2, -dU, dV, 1); +ObjPrim_SetVertexPosition(LaserEffect, 3, dU, dV, 1); + +ObjPrim_SetVertexIndex(LaserEffect, [0, 1, 2, 1, 2, 3]); + +task _CreateLaserParticle(float x, float y, float spdX, float spdY, float baseAng){ + + int effectLength = 45; + let x_speed = spdX; + let y_speed = spdY; + let z_add = rand(-5, 5); + + ascent(i in 0..effectLength){ + _PetalMovement(Interpolate_Decelerate(1, 0.5, i/effectLength), Interpolate_Decelerate(255, 0, i/effectLength)); + yield; + } + + task _PetalMovement(scale, alpha){ + + ObjParticleList_SetScale(LaserEffect, scale); + ObjParticleList_SetAngleZ(LaserEffect, baseAng); + ObjParticleList_SetPosition(LaserEffect, x, y, 1); + ObjParticleList_SetAlpha(LaserEffect, alpha); + + //Submits the current data to an instance, cleared every frame. + ObjParticleList_AddInstance(LaserEffect); + + x += x_speed; + y += y_speed; + baseAng += z_add; + + yield; + + } + +} + +// + +task _LaserSpriteRender( + img, int target, float targetAng, + int rectLeft, int rectTop, int rectRight, int rectBottom, + float scaleX, float scaleY, int renderPriority, float alpha, + float scaleSpeed + ){ + + int[] EnemyList = []; + let lasersprite = ObjPrim_Create(OBJ_SPRITE_2D); + + float scaleXBoost = 0; + float scaleXBoostMax = 0.05; + float ang = 180; + + ObjPrim_SetTexture(lasersprite, img); + ObjSprite2D_SetSourceRect(lasersprite, rectLeft, rectTop, rectRight, rectBottom); + ObjRender_SetScaleXYZ(lasersprite, 0, scaleY, 1); + ObjSprite2D_SetDestRect(lasersprite, -(rectRight-rectLeft)/2, 0, (rectRight-rectLeft)/2, rectTop-rectBottom); + Obj_SetRenderPriorityI(lasersprite, renderPriority); + ObjRender_SetAlpha(lasersprite, 0); + ObjRender_SetBlendType(lasersprite, BLEND_ADD_ARGB); + + async{ + loop{ + + if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && !ripplayer && IsPermitPlayerShot){ + + // Assumes the intersecting color is right next to the right of the original color + + if (length(EnemyList) > 0) {ObjSprite2D_SetSourceRect(lasersprite, rectRight, rectTop, rectRight+(rectRight-rectLeft), rectBottom);} + else{ObjSprite2D_SetSourceRect(lasersprite, rectLeft, rectTop, rectRight, rectBottom);} + + float targetx = ObjRender_GetX(target); + float targety = ObjRender_GetY(target); + + ObjRender_SetScaleX(lasersprite, min(scaleX+scaleXBoost, ObjRender_GetScaleX(lasersprite) + scaleSpeed)); + scaleXBoost = scaleXBoostMax * sin(ang); + + ObjRender_SetAlpha(lasersprite, min(alpha, ObjRender_GetAlpha(lasersprite)+alpha/5)); + ObjRender_SetAngleZ(lasersprite, targetAng); + ObjRender_SetPosition(lasersprite, targetx, targety, 1); + + ang += 25; + + yield; + + } + + else{ + ObjRender_SetScaleX(lasersprite, max(0, ObjRender_GetScaleX(lasersprite) - scaleSpeed)); + ObjRender_SetAlpha(lasersprite, max(0, ObjRender_GetAlpha(lasersprite)-alpha/5)); + yield; + } + + yield; + } + } + +} + +function _RenderLaser(target, float ang, float maxintersectX, float maxLength, float width, float speedLength, float dmg){ /* */ + + int[] EnemyList = []; + + float angRender = asin(maxintersectX/absolute(maxLength)); + //int laser = CreatePlayerShotA1(ObjRender_GetX(target), ObjRender_GetY(target), 0, ang, dmg, 9999999, 0); + int laser = CreateStraightLaserA1(ObjRender_GetX(target), ObjRender_GetY(target), ang-90, maxLength, width, 99999999, 0, 1); + ObjLaser_SetInvalidLength(laser, 0, 0); + ObjShot_SetDamage(laser, dmg); + ObjShot_SetAutoDelete(laser, false); + Obj_SetRenderPriorityI(laser, plrender-1); + _Follow(laser, target); + + _LaserSpriteRender( + plimg, laser, ang, + 256, 192, 384, 384, + 1, 20, plrender-1, shotAlpha, + 0.1 + ); + + // This also affects damage of the laser, not just effects + LaserHitEffect(EnemyList, laser, dmg); + + // When shot key is being held, create a line intersection that stretches across the laser. + + /* + Calculations: + + startx: x of target + + starty: y of target + + endx: x of laser + + endy: maxLength + + width = width of laser + */ + async{ + + loop{ + + if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && !ripplayer && IsPermitPlayerShot){ + + if(shotspeed % 5 == 0){ + ObjSound_Play(Base2); + } + + ObjShot_SetIntersectionEnable(laser, true); + + //ObjShot_SetIntersectionLine(laser, ObjRender_GetX(target), ObjRender_GetY(target), ObjRender_GetX(target)+maxintersectX, -maxLength, width); + //WriteLog(ObjMove_GetX(laserfwd)); + yield; + + } + + else{ + ObjShot_SetIntersectionEnable(laser, false); + ObjShot_SetPenetration(laser, 99999999); + yield; + } + + } + + } + + // After shot key is released, let the laser leave and then delete it. + + return laser; +} + +task LaserHitEffect(int[] EnemyList, int target, float basedmg){ + + async{ + loop{ + EnemyList = ObjCol_GetListOfIntersectedEnemyID(target); + yield; + } + } + + // Particle effects + async{ + loop{ + ascent(i in -1..length(EnemyList)-1){ + _CreateLaserParticle(ObjMove_GetX(EnemyList[i])+prand(-30, 30), ObjMove_GetY(EnemyList[i])+prand(-30, 30), [prand(-8, -5), prand(-4, 4), prand(5, 8)][prand_int(0, 2)], [prand(-8, -6), prand(6, 8)][prand_int(0, 1)], rand(0, 360)); + } + //Resort; + //WriteLog(EnemyList); + wait(rand_int(6, 9)); + } + } + + // Damage effects + +} +task _Follow(follower, followed){ + + while(!Obj_IsDeleted(follower)){ + float x = ObjRender_GetX(followed); + float y = ObjRender_GetY(followed); + ObjMove_SetPosition(follower, x, y); + yield; + } + +} \ No newline at end of file diff --git a/script/player/Narumi/Player_Main.dnh b/script/player/Narumi/Player_Main.dnh new file mode 100644 index 0000000..bcda0e0 --- /dev/null +++ b/script/player/Narumi/Player_Main.dnh @@ -0,0 +1,354 @@ +#TouhouDanmakufu[Player] +#ScriptVersion[3] +#ID["PL_NARUMI"] +#Title["Narumi Yatadera"] +#Text["Player 0"] + +//#Image["./mariremi_lib/mariremi_illust.png"] + +#ReplayName["Narumi"] + +#include "script/KevinSystem/kevin_system/Lib_Const.dnh" + +#include "script/KevinSystem/Kevin_PlayerLib.txt" +#include "script/KevinSystem/PlayerSoundLib.dnh" + +#include "./Player_Function.dnh" +#include "./Player_ShotConst.dnh" + +#include "script/KevinSystem/kevin_system/Kevin_ItemConst.txt" +#include "script/KevinSystem/kevin_system/Kevin_ItemLib.txt" + +let csd = GetCurrentScriptDirectory(); + +// Global Variables + +float maxX = GetStgFrameWidth(); +float maxY = GetStgFrameHeight(); + +// Images & Sound + +let teamimg = csd ~ "./playerlib/Player_Sheet.png"; +LoadTextureEx(teamimg, true, true); +//ObjRender_SetTextureFilterMip(teamimg, FILTER_LINEAR); + +let plimg = csd ~ "./playerlib/PlSheet_Narumi.png"; +LoadTextureEx(plimg, true, true); +ObjRender_SetTextureFilter(plimg, FILTER_NONE, FILTER_NONE, FILTER_NONE); + +let sndpath = csd ~ "./sound"; + +int[] _enemyArray = []; +int[] _existArray = []; +int[] _shotArray = []; + +bool isChain = false; +bool isUseSpecialWpn = false; +float curChain = 0; + +// Other stuff + +float playerX = 0; +float playerY = 0; + +let objPlayer = GetPlayerObjectID(); +int plrender = 42; + +bool ripplayer = false; +float shotspeed = 0; +float bombrand = 0; + +int grazecounter = 0; // For basic graze = PIV mechanic + +int shotAlpha = (GetAreaCommonData("Config", "PlayerShotOpacity", 255)*0.01)*255; + +float shotDamageOption = 4; +float shotScaleOption = 1; + +float shotDamageLaser = 2; +float shotScaleLaser = 1; + +float shotDamageSpecial = 5; +float shotScaleSpecial = 1; + +float[] PlayerSpd = [12, 6]; + +// Custom events for scoring mechanic + +const EV_PIV_100 = EV_USER + 100i; // Normal enemies and nons +const EV_PIV_250 = EV_USER + 101i; // Spells +const EV_PIV_500 = EV_USER + 102i; // Last Spells +const EV_PIV_2000 = EV_USER + 103i; // What. + +@Initialize{ + + if(!IsCommonDataAreaExists("PIV")){ + CreateCommonDataArea("PIV"); + SetAreaCommonData("PIV", "currentvalue", 10000); + SetAreaCommonData("PIV", "ChainAmount", 1); + } + else{} + + SetPlayerStateEndEnable(true); + + // Stuff + Parameter(); + RenderPlayer(); + BaseShot(); + SpecialWeapon(); + + Obj_SetRenderPriorityI(objPlayer, 43); + plrender = Obj_GetRenderPriorityI(objPlayer); + _SoundTask(); + + //SetIntersectionVisualization(true); // Debug + + _Mechanic(ripplayer, _enemyArray, _existArray, GetStgFrameWidth(), GetStgFrameHeight(), objPlayer, GetEnemyBossSceneObjectID(), 1, 2, 80); + + _ShowChain(); + //_HandleChainGauge(); + + //_HitboxRender(ripplayer, objPlayer, plimg, teamimg, 768, 192, 832, 256, 1536, 896, 2048, 1408, 0.5, 0.65); + SetShotAutoDeleteClip(96, 84, 96, 84); + + _Countdown(); + + // Shot data loading + LoadPlayerShotData(csd ~ "./Player_ShotData.dnh"); +} + +@MainLoop{ + _enemyArray = GetIntersectionRegistedEnemyID; + shotspeed += 1; // Managing the shot rate + //_shotArray = GetAllShotID(TARGET_PLAYER); + //UniversalAlphaHandle(_shotArray); + plrender = Obj_GetRenderPriorityI(objPlayer); + playerX = ObjMove_GetX(objPlayer); + playerY = ObjMove_GetY(objPlayer); + yield; +} + +@Event{ + alternative(GetEventType) + + // Delete effect + case(EV_DELETE_SHOT_PLAYER){ + + if(GetCommonDataPtr(EFFECTCUT_PTR, 0) >= 3){} + + else{ + + let graphic = GetEventArgument(2); + float[] position = GetEventArgument(1); + + let obj = CreatePlayerShotA1(position[0], position[1], 0, ObjMove_GetAngle(GetEventArgument(0))+rand(-15, 15), 0, 99999, graphic); + + ObjShot_SetIntersectionEnable(obj, false); + _DeleteEffect(obj, 1); + + } + //if(graphic == ELECTRIC_FIRE_ALT) {_DeleteEffectAlt(obj);} + //else{_DeleteEffect(obj);} + } + + // PIV-item spawning events + case(EV_PIV_100){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_100, arg[0], arg[1]); + } + + case(EV_PIV_250){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_250, arg[0], arg[1]); + } + + case(EV_PIV_500){ + let arg = GetEventArgument(0); + CreatePIVItem(PIV_500, arg[0], arg[1]); + } + + // Basic functionality events + case(EV_REQUEST_SPELL){ + SetScriptResult(false); + } + + case(EV_HIT){ + + } + + case(EV_CHAIN_MAX){ + + if(!isChain){ + ObjSound_Play(Shine); + isChain = true; + curChain = GetCommonDataPtr(POINTER_CHAIN, 1); + } + else{} + + } + + case(EV_CHAIN_RELEASE){ + + } + + case(EV_CHAIN_END){ + + SetAreaCommonData("PIV", "ChainAmount", 1); + isChain = false; + + // Increase rank depending on curChain (>= 32), then reset curChain. MAX CHAIN increases rank by 0.4. + + if(curChain >= 32){ + SetCommonData("Rank", clamp(GetCommonData("Rank", 1) + Interpolate_Linear(0.25, 0.5, curChain/64), GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); + } + + curChain = 1; + + } + + case(EV_PLAYER_SHOOTDOWN){ + + ObjSound_Play(PlayerDie2); + SetPlayerSpell(0); + ripplayer = true; + DeleteShotAll(TYPE_SHOT, TYPE_ITEM); + SetCommonData("Rank", clamp(GetCommonData("Rank", 1) * 0.75, GetCommonData("MinRank", 1), GetCommonData("MaxRank", 12))); + _DeathMove(); + + } + + case(EV_PLAYER_REBIRTH){ + ripplayer = false; + SetPlayerInvincibilityFrame(180); + //_Countdown(); + _SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, 150); + + } + + case(EV_GRAZE){ + + } +} + +@Finalize{ + +} + + +// Basic player parameters + +task Parameter(){ + + // im trying to not be collected by the player but their item scope is dummy thicc and im alerted by its cheek + SetPlayerItemScope(360); + + SetPlayerLife(9); // Debug + SetPlayerSpell(0); + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); // (original: 5.25/2.0) + SetPlayerRebirthFrame(0); // No bombs + SetPlayerDownStateFrame(90); + SetPlayerAutoItemCollectLine(GetStgFrameHeight/3); + SetPlayerRebirthLossFrame(0); + ObjPlayer_AddIntersectionCircleA1(objPlayer, 0, 0, 2, 40); + +} + +// Player render + +task RenderPlayer(){ + + // Why is this movement code so cursed jesus fucking christ + + float scale = 1; // Scalies + int frame = 0; + int spd = 12; + int frame_hbox = 0; + + ObjPrim_SetTexture(objPlayer, plimg); + ObjSprite2D_SetSourceRect(objPlayer, 0, 0, 192, 192); + ObjSprite2D_SetDestCenter(objPlayer); + Obj_SetRenderPriorityI(objPlayer, plrender); + ObjRender_SetScaleXYZ(objPlayer, scale, scale, 1); + + int hitbox = ObjPrim_Create(OBJ_SPRITE_2D); + + ObjPrim_SetTexture(hitbox, plimg); + ObjSprite2D_SetSourceRect(hitbox, 384, 0, 448, 64); + ObjSprite2D_SetDestCenter(hitbox); + ObjRender_SetScaleXYZ(hitbox, scale, scale, 1); + ObjRender_SetBlendType(hitbox, BLEND_ALPHA); + Obj_SetRenderPriorityI(hitbox, 79); + + Obj_SetVisible(hitbox, false); + + // Lower "speed" parameter = FASTER SPEED + + // FOR WHEN ONLY IDLE SPRITES ARE DONE + + while(true){ + + frame++; + frame_hbox++; + + ObjRender_SetPosition(hitbox, playerX, playerY, 1); + + if(ripplayer){ + ObjSprite2D_SetSourceRect(objPlayer, 0, 384, 192, 576); + Obj_SetVisible(hitbox, false); + } + + else{ + + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + + ObjSprite2D_SetSourceRect(hitbox, 384+64*floor(frame_hbox/9), 0, 64+384+64*floor(frame_hbox/9), 64); + Obj_SetVisible(hitbox, true); + + _RenderPlayerMovement(objPlayer, frame, 0, 192, 192, 192, scale, 2, spd); + + } + + else{ + + _RenderPlayerMovement(objPlayer, frame, 0, 0, 192, 192, scale, 2, spd); + + Obj_SetVisible(hitbox, false); + + } + + } + + if (frame >= (2*spd-1)){frame = 0;} + if (frame_hbox >= (3*9-1)){frame_hbox = 0;} + + yield; + + } + +} + +task _DeathMove(){ + + int afterimage = ObjPrim_Create(OBJ_SPRITE_2D); + + ObjPrim_SetTexture(afterimage, plimg); + ObjSprite2D_SetSourceRect(afterimage, 0, 384, 192, 576); + ObjSprite2D_SetDestCenter(afterimage); + ObjRender_SetBlendType(afterimage, BLEND_ALPHA); + Obj_SetRenderPriorityI(afterimage, 40); + + float[] curdest = [playerX, playerY]; + float[] dest = [clamp(playerX-256, 0, GetStgFrameWidth()), playerY]; + + SetPlayerRebirthPosition(dest[0], dest[1]); + + ascent(i in 0..30){ + ObjRender_SetPosition(afterimage, Interpolate_Decelerate(curdest[0], dest[0], i/30), playerY, 1); + yield; + } + + wait(60); + + Obj_Delete(afterimage); + +} \ No newline at end of file diff --git a/script/player/Narumi/Player_ShotConst.dnh b/script/player/Narumi/Player_ShotConst.dnh new file mode 100644 index 0000000..a7d70ae --- /dev/null +++ b/script/player/Narumi/Player_ShotConst.dnh @@ -0,0 +1,9 @@ +let current = GetCurrentScriptDirectory(); +let path = current ~ "Player_ShotData.dnh"; +LoadPlayerShotData(path); +// ----- + +const AMULET = 1; +const GOLEM = 2; + + diff --git a/script/player/Narumi/Player_ShotData.dnh b/script/player/Narumi/Player_ShotData.dnh new file mode 100644 index 0000000..60a1efc --- /dev/null +++ b/script/player/Narumi/Player_ShotData.dnh @@ -0,0 +1,29 @@ +shot_image = "./playerlib/PlSheet_Narumi.png" + +ShotData{ + id = 0 // Dummy + rect = (0,0,0,0) + render = ALPHA + alpha = 0 + collision = 32 +} + +// Fire + +ShotData{ + id = 1 + rect = (640, 256, 768, 384) + render = ALPHA + alpha = 255 + collision = 64 // Hitbox of arrows is not centered on the sprite +} + +// Golem + +ShotData{ + id = 2 + rect = (640, 0, 896, 256) + render = ALPHA + alpha = 255 + collision = 128 // Hitbox of arrows is not centered on the sprite +} \ No newline at end of file diff --git a/script/player/Narumi/desc.txt b/script/player/Narumi/desc.txt new file mode 100644 index 0000000..e69de29 diff --git a/script/player/Narumi/playerlib/PlSheet_Kouryuu.png b/script/player/Narumi/playerlib/PlSheet_Kouryuu.png new file mode 100644 index 0000000..aaf447b Binary files /dev/null and b/script/player/Narumi/playerlib/PlSheet_Kouryuu.png differ diff --git a/script/player/Narumi/playerlib/PlSheet_Narumi.png b/script/player/Narumi/playerlib/PlSheet_Narumi.png new file mode 100644 index 0000000..79783ee Binary files /dev/null and b/script/player/Narumi/playerlib/PlSheet_Narumi.png differ diff --git a/script/player/Narumi/playerlib/RAW/KouryuuPalette.aseprite b/script/player/Narumi/playerlib/RAW/KouryuuPalette.aseprite new file mode 100644 index 0000000..903fad5 Binary files /dev/null and b/script/player/Narumi/playerlib/RAW/KouryuuPalette.aseprite differ diff --git a/script/player/Narumi/playerlib/RAW/soGay.aseprite b/script/player/Narumi/playerlib/RAW/soGay.aseprite new file mode 100644 index 0000000..373e908 Binary files /dev/null and b/script/player/Narumi/playerlib/RAW/soGay.aseprite differ diff --git a/script/player/Narumi/playerlib/RAW/soTrue.aseprite b/script/player/Narumi/playerlib/RAW/soTrue.aseprite new file mode 100644 index 0000000..c095ade Binary files /dev/null and b/script/player/Narumi/playerlib/RAW/soTrue.aseprite differ diff --git a/script/player/Narumi/sound/CK Music Factory/air01.wav b/script/player/Narumi/sound/CK Music Factory/air01.wav new file mode 100644 index 0000000..bc2c0ed Binary files /dev/null and b/script/player/Narumi/sound/CK Music Factory/air01.wav differ diff --git a/script/player/Narumi/sound/CK Music Factory/air02.wav b/script/player/Narumi/sound/CK Music Factory/air02.wav new file mode 100644 index 0000000..f7e5ed8 Binary files /dev/null and b/script/player/Narumi/sound/CK Music Factory/air02.wav differ diff --git a/script/player/Narumi/sound/CK Music Factory/laser01.wav b/script/player/Narumi/sound/CK Music Factory/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/Narumi/sound/CK Music Factory/laser01.wav differ diff --git a/script/player/Narumi/sound/CK Music Factory/slash01.wav b/script/player/Narumi/sound/CK Music Factory/slash01.wav new file mode 100644 index 0000000..364dfca Binary files /dev/null and b/script/player/Narumi/sound/CK Music Factory/slash01.wav differ diff --git a/script/player/Narumi/sound/CK Music Factory/wind01.wav b/script/player/Narumi/sound/CK Music Factory/wind01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/Narumi/sound/CK Music Factory/wind01.wav differ diff --git a/script/player/Narumi/sound/TAM Music Factory/se04.wav b/script/player/Narumi/sound/TAM Music Factory/se04.wav new file mode 100644 index 0000000..ca33890 Binary files /dev/null and b/script/player/Narumi/sound/TAM Music Factory/se04.wav differ diff --git a/script/player/Narumi/sound/TAM Music Factory/status4.wav b/script/player/Narumi/sound/TAM Music Factory/status4.wav new file mode 100644 index 0000000..1227a08 Binary files /dev/null and b/script/player/Narumi/sound/TAM Music Factory/status4.wav differ diff --git a/script/player/Narumi/sound/TAM Music Factory/tama2.wav b/script/player/Narumi/sound/TAM Music Factory/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/Narumi/sound/TAM Music Factory/tama2.wav differ diff --git a/script/player/Narumi/sound/bfxr_scythecall.wav b/script/player/Narumi/sound/bfxr_scythecall.wav new file mode 100644 index 0000000..99b3040 Binary files /dev/null and b/script/player/Narumi/sound/bfxr_scythecall.wav differ diff --git a/script/player/Narumi/sound/bfxr_splash.wav b/script/player/Narumi/sound/bfxr_splash.wav new file mode 100644 index 0000000..6a4d49d Binary files /dev/null and b/script/player/Narumi/sound/bfxr_splash.wav differ diff --git a/script/player/Narumi/sound/bfxr_teleporthigh.wav b/script/player/Narumi/sound/bfxr_teleporthigh.wav new file mode 100644 index 0000000..cc8b9ae --- /dev/null +++ b/script/player/Narumi/sound/bfxr_teleporthigh.wav @@ -0,0 +1 @@ +2,0.57,,0.3442,,0.2691,0.3,0.2179,,0.3445,,,,,,,,,,,0.2992,,0.5139,,,1,,,,,,,masterVolume \ No newline at end of file diff --git a/script/player/Narumi/sound/bfxr_teleportlow.wav b/script/player/Narumi/sound/bfxr_teleportlow.wav new file mode 100644 index 0000000..d55ce4b Binary files /dev/null and b/script/player/Narumi/sound/bfxr_teleportlow.wav differ diff --git a/script/player/Narumi/sound/bfxr_watershoot.wav b/script/player/Narumi/sound/bfxr_watershoot.wav new file mode 100644 index 0000000..6cfced3 Binary files /dev/null and b/script/player/Narumi/sound/bfxr_watershoot.wav differ diff --git a/script/player/Narumi/sound/birdcall05.wav b/script/player/Narumi/sound/birdcall05.wav new file mode 100644 index 0000000..ec6c7b9 Binary files /dev/null and b/script/player/Narumi/sound/birdcall05.wav differ diff --git a/script/player/Narumi/sound/hit01.wav b/script/player/Narumi/sound/hit01.wav new file mode 100644 index 0000000..0698a04 Binary files /dev/null and b/script/player/Narumi/sound/hit01.wav differ diff --git a/script/player/Narumi/sound/laser01.wav b/script/player/Narumi/sound/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/Narumi/sound/laser01.wav differ diff --git a/script/player/Narumi/sound/magic21.wav b/script/player/Narumi/sound/magic21.wav new file mode 100644 index 0000000..19714fe Binary files /dev/null and b/script/player/Narumi/sound/magic21.wav differ diff --git a/script/player/Narumi/sound/retrolaser.wav b/script/player/Narumi/sound/retrolaser.wav new file mode 100644 index 0000000..a58304e Binary files /dev/null and b/script/player/Narumi/sound/retrolaser.wav differ diff --git a/script/player/Narumi/sound/slash01.wav b/script/player/Narumi/sound/slash01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/Narumi/sound/slash01.wav differ diff --git a/script/player/Narumi/sound/tama2.wav b/script/player/Narumi/sound/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/Narumi/sound/tama2.wav differ diff --git a/script/player/RAW_DELETEINRC/PlSheet_Gunner.ase b/script/player/RAW_DELETEINRC/PlSheet_Gunner.ase new file mode 100644 index 0000000..06ce8df Binary files /dev/null and b/script/player/RAW_DELETEINRC/PlSheet_Gunner.ase differ diff --git a/script/player/RAW_DELETEINRC/playerArt.mdp b/script/player/RAW_DELETEINRC/playerArt.mdp new file mode 100644 index 0000000..5a425cd Binary files /dev/null and b/script/player/RAW_DELETEINRC/playerArt.mdp differ diff --git a/script/replay/GayGunner_Package_replay01.dat b/script/replay/GayGunner_Package_replay01.dat new file mode 100644 index 0000000..30b463c Binary files /dev/null and b/script/replay/GayGunner_Package_replay01.dat differ diff --git a/script/sample/Effect01.png b/script/sample/Effect01.png new file mode 100644 index 0000000..b9496d8 Binary files /dev/null and b/script/sample/Effect01.png differ diff --git a/script/sample/Effect02.png b/script/sample/Effect02.png new file mode 100644 index 0000000..9f20aa7 Binary files /dev/null and b/script/sample/Effect02.png differ diff --git a/script/sample/ExRumia.png b/script/sample/ExRumia.png new file mode 100644 index 0000000..1a065a8 Binary files /dev/null and b/script/sample/ExRumia.png differ diff --git a/script/sample/SampleA01.txt b/script/sample/SampleA01.txt new file mode 100644 index 0000000..7a7ac34 Binary files /dev/null and b/script/sample/SampleA01.txt differ diff --git a/script/sample/SampleA02.txt b/script/sample/SampleA02.txt new file mode 100644 index 0000000..d23d518 Binary files /dev/null and b/script/sample/SampleA02.txt differ diff --git a/script/sample/SampleA03.txt b/script/sample/SampleA03.txt new file mode 100644 index 0000000..9ce822f Binary files /dev/null and b/script/sample/SampleA03.txt differ diff --git a/script/sample/SampleB01.txt b/script/sample/SampleB01.txt new file mode 100644 index 0000000..3e7ee9f --- /dev/null +++ b/script/sample/SampleB01.txt @@ -0,0 +1,103 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["SampleB01"] +#Text["SampleB01: ObjPatternShot Demonstrations[r] Powered by Junko"] + +#include "script/default_system/Default_ShotConst.txt" + +let objEnemy; +let frame = 0; + +@Event { + alternative(GetEventType()) + case(EV_REQUEST_LIFE) { + SetScriptResult(500); + } +} + +@Initialize { + objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS); + ObjEnemy_Regist(objEnemy); + + let imgExRumia = GetCurrentScriptDirectory ~ "ExRumia.png"; + ObjPrim_SetTexture(objEnemy, imgExRumia); + ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(objEnemy); + + let cx = GetStgFrameWidth() / 2; + ObjMove_SetDestAtFrame(objEnemy, cx, 120, 60); + + SetPlayerInvincibilityFrame(600000); + + TShot(); +} + +@MainLoop { + let ex = ObjMove_GetX(objEnemy); + let ey = ObjMove_GetY(objEnemy); + + ObjEnemy_SetIntersectionCircleToShot(objEnemy, ex, ey, 32); + ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ex, ey, 24); + + yield; + + if (ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0) { + Obj_Delete(objEnemy); + CloseScript(GetOwnScriptID()); + return; + } +} + +task TShot() { + let objPattern1 = ObjPatternShot_Create(); + + ObjPatternShot_SetParentObject(objPattern1, objEnemy); + + ObjPatternShot_SetDelay(objPattern1, 12); + ObjPatternShot_SetGraphic(objPattern1, DS_BALL_S_RED); + + ObjPatternShot_SetSpeed(objPattern1, 2, 1); + ObjPatternShot_SetAngle(objPattern1, 90, 0); + + ObjPatternShot_SetPatternType(objPattern1, PATTERN_RING); + ObjPatternShot_SetShotCount(objPattern1, 22, 1); + + ObjPatternShot_SetShootRadius(objPattern1, 48); + + let objPattern2 = ObjPatternShot_Create(); + ObjPatternShot_CopySettings(objPattern2, objPattern1); + + ObjPatternShot_SetGraphic(objPattern2, DS_BALL_S_PURPLE); + + ObjPatternShot_SetSpeed(objPattern2, 1, 1); + + ObjPatternShot_SetShotCount(objPattern2, 10, 1); + + wait(60); + + let frame = 0; + while (ObjEnemy_GetInfo(objEnemy, INFO_LIFE) > 0) { + if (frame % 30 == 0) { + ObjPatternShot_SetBasePointOffsetCircle(objPattern1, rand(0, 360), 32); + ObjPatternShot_Fire(objPattern1); + } + + if (frame % 40 == 0 && frame > 75) { + for each (iX in [288, 96]) { + ObjPatternShot_SetBasePoint(objPattern2, iX, 144); + ObjPatternShot_SetBasePointOffsetCircle(objPattern2, rand(0, 360), 32); + + ObjPatternShot_SetAngle(objPattern2, rand(0, 360), 0); + + ObjPatternShot_Fire(objPattern2); + } + } + + frame++; + yield; + } + + Obj_Delete(objPattern1); + Obj_Delete(objPattern2); +} + diff --git a/script/sample/SampleB02.txt b/script/sample/SampleB02.txt new file mode 100644 index 0000000..45dab5b --- /dev/null +++ b/script/sample/SampleB02.txt @@ -0,0 +1,81 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["SampleB02"] +#Text["SampleB02: ObjPatternShot Transforms 1"] + +#include "script/default_system/Default_ShotConst.txt" + +let objEnemy; +let frame = 0; + +@Event { + alternative(GetEventType()) + case(EV_REQUEST_LIFE) { + SetScriptResult(500); + } +} + +@Initialize { + objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS); + ObjEnemy_Regist(objEnemy); + + let imgExRumia = GetCurrentScriptDirectory ~ "ExRumia.png"; + ObjPrim_SetTexture(objEnemy, imgExRumia); + ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(objEnemy); + + let cx = GetStgFrameWidth() / 2; + ObjMove_SetDestAtFrame(objEnemy, cx, 120, 60); + + TShot(); +} + +@MainLoop { + let ex = ObjMove_GetX(objEnemy); + let ey = ObjMove_GetY(objEnemy); + + ObjEnemy_SetIntersectionCircleToShot(objEnemy, ex, ey, 32); + ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ex, ey, 24); + + yield; + + if (ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0) { + Obj_Delete(objEnemy); + CloseScript(GetOwnScriptID()); + return; + } +} + +task TShot() { + let objPattern = ObjPatternShot_Create(); + + ObjPatternShot_SetParentObject(objPattern, objEnemy); + ObjPatternShot_SetPatternType(objPattern, PATTERN_ARROW); + + ObjPatternShot_SetDelay(objPattern, 12); + ObjPatternShot_SetGraphic(objPattern, DS_SCALE_BLUE); + + ObjPatternShot_SetSpeed(objPattern, 1.5, 1.2); + + ObjPatternShot_SetShotCount(objPattern, 3, 5); + + ObjPatternShot_AddTransform(objPattern, TRANSFORM_WAIT, 20); + ObjPatternShot_AddTransform(objPattern, TRANSFORM_ADD_SPEED_ANGLE, 900, 0, 0.015, 0); + + ObjPatternShot_SetShootRadius(objPattern, 32); + + wait(60); + + let frame = 0; + while (ObjEnemy_GetInfo(objEnemy, INFO_LIFE) > 0) { + ObjPatternShot_SetAngle(objPattern, rand(0, 360), 6); + + let ang_vel = 6.4 * sin(frame * 8); + ObjPatternShot_SetTransform(objPattern, 2, TRANSFORM_ANGULAR_MOVE, 30, ang_vel, 2); + + ObjPatternShot_Fire(objPattern); + + frame++; + wait(10); + } +} \ No newline at end of file diff --git a/script/sample/SampleB03.txt b/script/sample/SampleB03.txt new file mode 100644 index 0000000..2b6356b --- /dev/null +++ b/script/sample/SampleB03.txt @@ -0,0 +1,86 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["SampleB03"] +#Text["SampleB03: ObjPatternShot Transforms 2 : Transform Harder"] + +#include "script/default_system/Default_ShotConst.txt" + +let objEnemy; +let frame = 0; + +@Event { + alternative(GetEventType()) + case(EV_REQUEST_LIFE) { + SetScriptResult(500); + } +} + +@Initialize { + objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS); + ObjEnemy_Regist(objEnemy); + + let imgExRumia = GetCurrentScriptDirectory ~ "ExRumia.png"; + ObjPrim_SetTexture(objEnemy, imgExRumia); + ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(objEnemy); + + let cx = GetStgFrameWidth() / 2; + ObjMove_SetDestAtFrame(objEnemy, cx, 120, 60); + + SetPlayerInvincibilityFrame(600000); + + TShot(); +} + +@MainLoop { + let ex = ObjMove_GetX(objEnemy); + let ey = ObjMove_GetY(objEnemy); + + ObjEnemy_SetIntersectionCircleToShot(objEnemy, ex, ey, 32); + ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ex, ey, 24); + + yield; + + if (ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0) { + Obj_Delete(objEnemy); + CloseScript(GetOwnScriptID()); + return; + } +} + +task TShot() { + let objPattern = ObjPatternShot_Create(); + + ObjPatternShot_SetParentObject(objPattern, objEnemy); + ObjPatternShot_SetPatternType(objPattern, PATTERN_RING); + + ObjPatternShot_SetDelay(objPattern, 12); + ObjPatternShot_SetGraphic(objPattern, DS_BALL_S_RED); + + ObjPatternShot_SetSpeed(objPattern, 2, 1.2); + + ObjPatternShot_SetShotCount(objPattern, 16, 1); + ObjPatternShot_SetInitialBlendMode(objPattern, BLEND_ADD_ARGB); + + ObjPatternShot_AddTransform(objPattern, TRANSFORM_WAIT, 20); + ObjPatternShot_AddTransform(objPattern, TRANSFORM_N_DECEL_CHANGE, 25, 5, 1, 2.7, 10.12); //Think of Aunn's first spell + ObjPatternShot_AddTransform(objPattern, TRANSFORM_ADDPATTERN_A1, 0, 0, NO_CHANGE); + ObjPatternShot_AddTransform(objPattern, TRANSFORM_WAIT, 60); + ObjPatternShot_AddTransform(objPattern, TRANSFORM_BLEND_CHANGE, BLEND_ALPHA); + ObjPatternShot_AddTransform(objPattern, TRANSFORM_GRAPHIC_CHANGE, DS_RICE_S_RED); + ObjPatternShot_AddTransform(objPattern, TRANSFORM_TO_SPEED_ANGLE, 60, 1.8, NO_CHANGE); + + wait(60); + + let frame = 0; + while (ObjEnemy_GetInfo(objEnemy, INFO_LIFE) > 0) { + ObjPatternShot_SetAngle(objPattern, rand(0, 360), 0); + + ObjPatternShot_SetTransform(objPattern, 1, TRANSFORM_N_DECEL_CHANGE, 25, 5, 1, 2.7, 14 * sin(frame * 6)); + + ObjPatternShot_Fire(objPattern); + + frame++; + wait(4); + } +} \ No newline at end of file diff --git a/script/sample/SampleB04.txt b/script/sample/SampleB04.txt new file mode 100644 index 0000000..0a31b6d --- /dev/null +++ b/script/sample/SampleB04.txt @@ -0,0 +1,87 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["SampleB04"] +#Text["SampleB04: ObjPatternShot Transforms 3 : 14 Werewolves[r]Transformation"] + +#include "script/default_system/Default_ShotConst.txt" + +let objEnemy; +let frame = 0; + +@Event { + alternative(GetEventType()) + case(EV_REQUEST_LIFE) { + SetScriptResult(2500); + } +} + +@Initialize { + objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS); + ObjEnemy_Regist(objEnemy); + + let imgExRumia = GetCurrentScriptDirectory ~ "ExRumia.png"; + ObjPrim_SetTexture(objEnemy, imgExRumia); + ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(objEnemy); + + SetPlayerInvincibilityFrame(6000000); + ObjMove_SetDestAtFrame(objEnemy, 192, 224, 60); + + TShot(); +} + +@MainLoop { + let ex = ObjMove_GetX(objEnemy); + let ey = ObjMove_GetY(objEnemy); + + ObjEnemy_SetIntersectionCircleToShot(objEnemy, ex, ey, 32); + ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ex, ey, 24); + + yield; + + if (ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0) { + Obj_Delete(objEnemy); + CloseScript(GetOwnScriptID()); + return; + } +} + +task TShot() { + wait(90); + while (ObjEnemy_GetInfo(objEnemy, INFO_LIFE) > 0) { + _TShot(1, DS_RICE_M_PURPLE); + wait(330); + _TShot(-1, DS_RICE_M_RED); + wait(330); + } +} + +task _TShot(dir, graphic) { + if (ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0) { return; } + + let objPattern = ObjPatternShot_Create(); + + ObjPatternShot_SetParentObject(objPattern, objEnemy); + ObjPatternShot_SetPatternType(objPattern, PATTERN_RING); + ObjPatternShot_SetShotType(objPattern, OBJ_CURVE_LASER); + + ObjPatternShot_SetDelay(objPattern, 0); + ObjPatternShot_SetGraphic(objPattern, graphic); + + ObjPatternShot_SetAngle(objPattern, rand(0, 360), 0); + ObjPatternShot_SetSpeed(objPattern, 6, 6); + + ObjPatternShot_SetShotCount(objPattern, 28, 1); + ObjPatternShot_SetLaserParameter(objPattern, 8, 128); + + ObjPatternShot_AddTransform(objPattern, TRANSFORM_ADD_SPEED_ANGLE, 30, 0, 0, -8 * dir); + ObjPatternShot_AddTransform(objPattern, TRANSFORM_ADD_SPEED_ANGLE, 30, 30, 0, 8 * dir); + ObjPatternShot_AddTransform(objPattern, TRANSFORM_ADD_SPEED_ANGLE, 30, 60, -0.12, -4 * dir); + ObjPatternShot_AddTransform(objPattern, TRANSFORM_ADD_SPEED_ANGLE, 30, 90, 0, 4 * dir); + ObjPatternShot_AddTransform(objPattern, TRANSFORM_ADD_SPEED_ANGLE, 30, 120, 0, -8 * dir); + ObjPatternShot_AddTransform(objPattern, TRANSFORM_ADD_SPEED_ANGLE, 45, 150, 0, 7 * dir); + + ObjPatternShot_Fire(objPattern); + + Obj_Delete(objPattern); +} diff --git a/script/sample/SampleE01.txt b/script/sample/SampleE01.txt new file mode 100644 index 0000000..57c8e14 Binary files /dev/null and b/script/sample/SampleE01.txt differ diff --git a/script/sample/SampleE02.txt b/script/sample/SampleE02.txt new file mode 100644 index 0000000..f46ac86 Binary files /dev/null and b/script/sample/SampleE02.txt differ diff --git a/script/sample/SamplePS01.txt b/script/sample/SamplePS01.txt new file mode 100644 index 0000000..6f01cb3 --- /dev/null +++ b/script/sample/SamplePS01.txt @@ -0,0 +1,40 @@ +#東方弾幕風[Stage] +#ScriptVersion[3] +#Title["SamplePS01"] +#Text["SamplePS01:ピクセルシェーダ:モノトーン"] +#Background["script/default_system/Default_Background_IceMountain.txt"] + +@Initialize +{ + TSamplePS1(); +} + +@MainLoop +{ + yield; +} + +task TSamplePS1 +{ + //パス設定 + let dir = GetCurrentScriptDirectory(); + let pathShader = dir ~ "SamplePS01_HLSL.txt"; + + //シェーダ生成 + let objShader = ObjShader_Create(); + ObjShader_SetShaderF(objShader, pathShader); + ObjShader_SetTechnique(objShader, "TecMonotone"); + + loop + { + //特定の描画優先度にシェーダを適応 + SetShaderI(objShader, 0, 100); + loop(180){yield;} + + //シェーダ解除 + ResetShaderI(0, 100); + loop(180){yield;} + } + +} + diff --git a/script/sample/SamplePS01_HLSL.txt b/script/sample/SamplePS01_HLSL.txt new file mode 100644 index 0000000..afb8140 --- /dev/null +++ b/script/sample/SamplePS01_HLSL.txt @@ -0,0 +1,59 @@ +//================================================================ +//ݒl +//Texture +sampler sampler0_ : register(s0); + +//================================================================ +//-------------------------------- +//sNZVF[_͒l +struct PS_INPUT +{ + float4 diffuse : COLOR0; //fBt[YF + float2 texCoord : TEXCOORD0; //eNX`W + float2 vPos : VPOS; //`W +}; + +//-------------------------------- +//sNZVF[_o͒l +struct PS_OUTPUT +{ + float4 color : COLOR0; //o͐F +}; + + +//================================================================ +// VF[_ +//-------------------------------- +//sNZVF[_ +PS_OUTPUT PsMonotone( PS_INPUT In ) : COLOR0 +{ + PS_OUTPUT Out; + + //eNX`̐F + float4 colorTexture = tex2D(sampler0_, In.texCoord); + + //_fBt[YF + float4 colorDiffuse = In.diffuse; + + // + float4 color = colorTexture * colorDiffuse; + + //mg[̌vZ + Out.color.rgb = ( color.r + color.g + color.b ) * 0.3333f; + Out.color.a = color.a; + + return Out; +} + + +//================================================================ +//-------------------------------- +//technique +technique TecMonotone +{ + pass P0 + { + PixelShader = compile ps_3_0 PsMonotone(); + } +} + diff --git a/script/sample/SamplePS02.txt b/script/sample/SamplePS02.txt new file mode 100644 index 0000000..fef61a5 --- /dev/null +++ b/script/sample/SamplePS02.txt @@ -0,0 +1,36 @@ +#東方弾幕風[Stage] +#ScriptVersion[3] +#Title["SamplePS02"] +#Text["SamplePS02:ピクセルシェーダ:マスク"] +#Background["script/default_system/Default_Background_IceMountain.txt"] + +@Initialize +{ + TSamplePS2(); +} + +@MainLoop +{ + yield; +} + +task TSamplePS2 +{ + //パス設定 + let dir = GetCurrentScriptDirectory(); + let pathShader = dir ~ "SamplePS02_HLSL.txt"; + + //シェーダ生成 + let objShader = ObjShader_Create(); + ObjShader_SetShaderF(objShader, pathShader); + ObjShader_SetTechnique(objShader, "TecMask"); + + //シェーダにマスク画像を設定 + let pathMask = dir ~ "SamplePS02_Mask.png"; + ObjShader_SetTexture(objShader, "textureMask_", pathMask); + + //特定の描画優先度にシェーダを適応 + SetShaderI(objShader, 30, 100); + +} + diff --git a/script/sample/SamplePS02_HLSL.txt b/script/sample/SamplePS02_HLSL.txt new file mode 100644 index 0000000..694a5f6 --- /dev/null +++ b/script/sample/SamplePS02_HLSL.txt @@ -0,0 +1,85 @@ +//================================================================ +//ݒl +//Texture +sampler sampler0_ : register(s0); + +//-------------------------------- +//}XNpeNX` +//ʕ(}XNeNX`TCY) +const float SCREEN_WIDTH = 640; +const float SCREEN_HEIGHT = 480; +texture textureMask_; +sampler samplerMask_ = sampler_state +{ + Texture = ; +}; + + +//================================================================ +//-------------------------------- +//sNZVF[_͒l +struct PS_INPUT +{ + float4 diffuse : COLOR0; //fBt[YF + float2 texCoord : TEXCOORD0; //eNX`W + float2 vPos : VPOS; //`W +}; + +//-------------------------------- +//sNZVF[_o͒l +struct PS_OUTPUT +{ + float4 color : COLOR0; //o͐F +}; + + +//================================================================ +// VF[_ +//-------------------------------- +//sNZVF[_ +PS_OUTPUT PsMask( PS_INPUT In ) : COLOR0 +{ + PS_OUTPUT Out; + + //eNX`̐F + float4 colorTexture = tex2D(sampler0_, In.texCoord); + + //_fBt[YF + float4 colorDiffuse = In.diffuse; + + // + float4 color = colorTexture * colorDiffuse; + Out.color = color; + if(color.a > 0) + { + //-------------------------------- + //}XNp̃eNX`F擾 + //UVł̈ʒu͉摜t@C̉ƍ̊ + //Ⴆ΁A640x480̉摜̈ʒu(320,240)UVł0.5,0.5ɂȂB + float2 maskUV; + + //`悩}XNpeNX`̈ʒuvZ + maskUV.x = In.vPos.x / SCREEN_WIDTH; + maskUV.y = In.vPos.y / SCREEN_HEIGHT; + float4 colorMask = tex2D(samplerMask_, maskUV); + + //}XNRGBlo͌ʂ̃lƂč + Out.color.a = ( colorMask.r + colorMask.g + colorMask.b ) * 0.3333f * color.a; + } + + + return Out; +} + + +//================================================================ +//-------------------------------- +//technique +technique TecMask +{ + pass P0 + { + PixelShader = compile ps_3_0 PsMask(); + } +} + diff --git a/script/sample/SamplePS02_Mask.png b/script/sample/SamplePS02_Mask.png new file mode 100644 index 0000000..90b87aa Binary files /dev/null and b/script/sample/SamplePS02_Mask.png differ diff --git a/script/sample/SamplePS03.txt b/script/sample/SamplePS03.txt new file mode 100644 index 0000000..cad4ec1 --- /dev/null +++ b/script/sample/SamplePS03.txt @@ -0,0 +1,193 @@ +#東方弾幕風[Single] +#ScriptVersion[3] +#Title["SamplePS03"] +#Text["SamplePS03:ピクセルシェーダ:ボス周囲のゆらぎエフェクト"] +#Background["script/default_system/Default_Background_IceMountain.txt"] + + +//デフォルト弾画像をロード +#include"script/default_system/Default_ShotConst.txt" + +//---------------------------------------------------- +//グローバル変数宣言 +//この位置で宣言した変数はスクリプト全体で有効です。 +//ただしこの箇所での変数への代入は、定数以外の代入は行えません。 +//(実行順序が保障されないため乱数などの使用はできません) +//---------------------------------------------------- +let objEnemy; //敵オブジェクト +let objPlayer; //自機オブジェクト +let frame = 0; //敵動作に使用するカウンタ(@MainLoopで1づつ増加させます) + +//---------------------------------------------------- +//敵の動作 +//---------------------------------------------------- +@Event +{ + alternative(GetEventType()) + case(EV_REQUEST_LIFE) + { + //敵ライフを要求された + SetScriptResult(500);//ライフを500に設定 + } +} + +@Initialize +{ + //自機オブジェクト取得 + objPlayer = GetPlayerObjectID(); + + //敵オブジェクトを生成し登録 + objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS); + ObjEnemy_Regist(objEnemy); + + //敵画像の設定 + let imgExRumia = GetCurrentScriptDirectory ~ "ExRumia.png"; //敵画像ファイル + ObjPrim_SetTexture(objEnemy, imgExRumia); //画像ファイルを読み込む + ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64); //描画元矩形を(64,1) - (127,64)に設定 + ObjSprite2D_SetDestCenter(objEnemy); //描画先を中心(0, 0)に設定 + + //座標(cx, 120)へ60フレームかけて移動する + let cx = GetStgFrameWidth() / 2;//STGシーンの中心x座標を取得 + ObjMove_SetDestAtFrame(objEnemy, cx, 120, 60); + + //let objScene = GetEnemyBossSceneObjectID(); + //ObjEnemyBossScene_StartSpell(objScene); + + TWaveCircle(); +} + +@MainLoop +{ + //敵の座標を取得 + let ex = ObjMove_GetX(objEnemy); + let ey = ObjMove_GetY(objEnemy); + + if(frame == 90) + { + let px = GetPlayerX(); + ObjMove_SetDestAtFrame(objEnemy, rand(192-100, 192+100), rand(50, 200), 60); + } + + if(frame == 180) + { + //frameが180になったら実行される部分 + //自機の座標を取得 + let px = GetPlayerX(); + let py = GetPlayerY(); + + //敵からみた自機方向の角度を求める。 + let angleToPlayer = atan2(py - ey, px - ex); + + //angleを-30から15ずつ増加させ5WAYにする + let angle=0; + while(angle<360) + {//(angle:15°間隔で0~360まで) + //一定時間で自機方向へ角度を変える弾 + //弾を作成する。 + let obj = CreateShotA2(ex, ey, 5, angle, -0.10, 1, DS_RICE_S_BLUE, 30); + //発射後60フレーム目に、自機方向を基準に角度変更するように設定 + ObjMove_AddPatternA4(obj, 60, 3, 0, 0, 0, 3, objPlayer, NO_CHANGE); + angle += 15; + } + + frame = 0;//弾を出したらframeを0にする + } + + //当たり判定登録 + ObjEnemy_SetIntersectionCircleToShot(objEnemy, ex, ey, 32);//当たり判定(自機弾用)登録 + ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ex, ey, 24);//当たり判定(体当たり用)登録 + + //カウンタに1追加 + frame++; + + //ライフ0処理 + if(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0) + { + //ライフが0になったら即座に終了 + //本来は爆発エフェクトのタスクを登録し、 + //エフェクト終了を待って、スクリプトを終了します。 + yield; + Obj_Delete(objEnemy); + CloseScript(GetOwnScriptID()); + return; + } + + yield; +} + + +//---------------------------------------------------- +//ボス周囲のゆらぎエフェクト +//---------------------------------------------------- +task TWaveCircle() +{ + //レンダリングターゲットに使用するテクスチャ + let renderTexture = GetReservedRenderTargetName(0); + + let frame = 0; //フレーム + let baseEffectRadius = 128; //基準エフェクト半径 + let outerFluct = 16; //エフェクト半径の最大変化量 + let effectRadius = 0; //エフェクト半径 + + + let priEffectMin = 20; //エフェクトをかける最小優先度 + let priEffectMax = 28; //エフェクトをかける最大優先度 + + //背景のみエフェクトの対象とする + //エフェクトの描画でまかなえるため、 + //優先度20~28の通常描画を無効にする。 + SetInvalidRenderPriorityA1(priEffectMin, priEffectMax); + + let frameWidth = GetStgFrameWidth(); + let frameHeight = GetStgFrameHeight(); + let frameLeft = GetStgFrameLeft(); + let frameRight = frameLeft + frameWidth; + let frameTop = GetStgFrameTop(); + let frameBottom = frameTop + frameHeight; + + + //-------------------------------- + //ゆがみオブジェクト + let objWave = ObjPrim_Create(OBJ_SPRITE_2D); //2Dスプライトオブジェクト生成 + Obj_SetRenderPriorityI(objWave, 25); //描画優先度を設定 + ObjPrim_SetTexture(objWave, renderTexture); //テクスチャを設定 + ObjSprite2D_SetSourceRect(objWave, frameLeft, frameTop, frameRight, frameBottom); + ObjSprite2D_SetDestRect(objWave, 0, 0, frameWidth, frameHeight); + Obj_SetRenderPriorityI(objWave, priEffectMax + 1); + + //ゆがみオブジェクトにシェーダを設定 + let pathShader = GetCurrentScriptDirectory ~ "SamplePS03_HLSL.txt"; + ObjShader_SetShaderF(objWave, pathShader); + ObjShader_SetTechnique(objWave, "TecWave"); + + + //ボスのライフが0になるまでエフェクトをかける。 + let objEnemy = GetEnemyBossObjectID[0]; + while(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) > 0) + { + //エフェクト半径 + effectRadius = baseEffectRadius + outerFluct * sin(frame*4); + + let enemyX = ObjMove_GetX(objEnemy); //敵座標X + let enemyY = ObjMove_GetY(objEnemy); //敵座標Y + + //-------------------------------- + //優先度20~28(背景)をエフェクト用のテクスチャに描画 + //シェーダ解除 + RenderToTextureA1(renderTexture, priEffectMin, priEffectMax, true); + + //-------------------------------- + //シェーダにパラメータを設定 + ObjShader_SetFloat(objWave, "frame_", frame); + ObjShader_SetFloat(objWave, "enemyX_", enemyX + frameLeft); + ObjShader_SetFloat(objWave, "enemyY_", enemyY + frameTop); + ObjShader_SetFloat(objWave, "waveRadius_", effectRadius); + + frame++; + yield; + } + + //エフェクト用オブジェクト削除 + Obj_Delete(objWave); + ClearInvalidRenderPriority(); +} diff --git a/script/sample/SamplePS03_HLSL.txt b/script/sample/SamplePS03_HLSL.txt new file mode 100644 index 0000000..0705a31 --- /dev/null +++ b/script/sample/SamplePS03_HLSL.txt @@ -0,0 +1,107 @@ + +//================================================================ +//ݒl +//Texture +sampler sampler0_ : register(s0); + +//-------------------------------- +//䂪ݐpp[^ +static const float RENDER_WIDTH = 1024; //_OeNX`̕ +static const float RENDER_HEIGHT = 1024; //_OeNX`̍ + +float frame_; //t[ +float enemyX_; //G̈ʒuX +float enemyY_; //G̈ʒuY +float waveRadius_; //GtFNg̔a + + +//================================================================ +//-------------------------------- +//sNZVF[_͒l +struct PS_INPUT +{ + float4 diffuse : COLOR0; //fBt[YF + float2 texCoord : TEXCOORD0; //eNX`W + float2 vPos : VPOS; //`W +}; + +//-------------------------------- +//sNZVF[_o͒l +struct PS_OUTPUT +{ + float4 color : COLOR0; //o͐F +}; + + +//================================================================ +// VF[_ +//-------------------------------- +//sNZVF[_ +PS_OUTPUT PsWave( PS_INPUT In ) : COLOR0 +{ + PS_OUTPUT Out; + + //-------------------------------- + //炬vZ + float dist2 = pow(In.vPos.x-enemyX_ ,2) + pow(In.vPos.y-enemyY_ ,2); + float dist = sqrt(dist2); + float sinTheta = (In.vPos.y - enemyY_) / dist; + float cosTheta = (In.vPos.x - enemyX_) / dist; + + //cݍ쐬psinɎgppxp[^ + float angle = In.vPos.y - enemyY_ + In.vPos.x - enemyX_ + frame_; + angle = radians(angle); + + //YsNZ̘c݂̔avZ + //GtFNga1/16ő̘cݕƂ + float waveRadius = waveRadius_ + waveRadius_/16 * (-1 + sin(angle)); + + //S狗قlje + float powerRatio = (waveRadius - dist) / waveRadius; + if(powerRatio < 0){powerRatio = 0;} + + //F擾ʒũoCAXl + float biasRadius = waveRadius * powerRatio; + float biasX = biasRadius * cosTheta; + float biasY = biasRadius * sinTheta; + + //eNX`̐F擾ʒu + float2 texUV; + texUV.x = -biasX / RENDER_WIDTH + In.texCoord.x; + texUV.y = -biasY / RENDER_HEIGHT + In.texCoord.y; + + + //-------------------------------- + //eNX`̐F + float4 colorTexture = tex2D(sampler0_, texUV); + + //_fBt[YF + float4 colorDiffuse = In.diffuse; + + // + float4 color = colorTexture * colorDiffuse; + + //FԂۂω + if(powerRatio > 0) + { + color.g = color.g * (1 - powerRatio); + color.b = color.b * (1 - powerRatio); + } + + Out.color = color; + + return Out; +} + + +//================================================================ +//-------------------------------- +//technique +technique TecWave +{ + pass P0 + { + PixelShader = compile ps_3_0 PsWave(); + } +} + diff --git a/script/sample/SampleRB01.txt b/script/sample/SampleRB01.txt new file mode 100644 index 0000000..7b86ccb Binary files /dev/null and b/script/sample/SampleRB01.txt differ diff --git a/script/sample/SampleRB02.txt b/script/sample/SampleRB02.txt new file mode 100644 index 0000000..af6bdb5 Binary files /dev/null and b/script/sample/SampleRB02.txt differ diff --git a/script/sample/SampleRB03.txt b/script/sample/SampleRB03.txt new file mode 100644 index 0000000..e8c5850 Binary files /dev/null and b/script/sample/SampleRB03.txt differ diff --git a/script/sample/SampleRC01.txt b/script/sample/SampleRC01.txt new file mode 100644 index 0000000..95f3658 --- /dev/null +++ b/script/sample/SampleRC01.txt @@ -0,0 +1,78 @@ +#TouhouDanmakufu[Stage] +#ScriptVersion[3] +#Title["SampleRC01"] +#Text["SampleRC01: Particle Rendering"] + +@Initialize { + TSample(); +} + +@MainLoop { + yield; +} + +task TSample() { + let dir = GetCurrentScriptDirectory(); + + let obj = ObjParticleList_Create(OBJ_PARTICLE_LIST_2D); + + Obj_SetRenderPriorityI(obj, 21); + ObjPrim_SetTexture(obj, dir ~ "Effect01.png"); + + ObjRender_SetBlendType(obj, BLEND_ADD_ARGB); + + //You may treat a 2D particle list object as a 2D primitive object. + ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLELIST); + ObjPrim_SetVertexCount(obj, 4); + + ObjPrim_SetVertexUVT(obj, 0, 140, 39); + ObjPrim_SetVertexUVT(obj, 1, 186, 39); + ObjPrim_SetVertexUVT(obj, 2, 140, 86); + ObjPrim_SetVertexUVT(obj, 3, 186, 86); + ObjPrim_SetVertexPosition(obj, 0, -46 / 2, -47 / 2, 1); + ObjPrim_SetVertexPosition(obj, 1, 46 / 2, -47 / 2, 1); + ObjPrim_SetVertexPosition(obj, 2, -46 / 2, 47 / 2, 1); + ObjPrim_SetVertexPosition(obj, 3, 46 / 2, 47 / 2, 1); + + //This is absolutely necessary, rendering will not be performed otherwise. + ObjPrim_SetVertexIndex(obj, [0, 1, 2, 1, 2, 3]); + + loop { + CreateParticle(); + yield; + } + + task CreateParticle() { + let x = rand(0, 384); + let y = rand(0, 448); + let x_speed = rand(-1, 1); + let y_speed = rand(-1, 1); + let z_angle = rand(0, 360); + let z_add = rand(-5, 5); + let scale = rand(0.3, 0.7); + + let timer_begin = floor(rand(10, 30 + 1)); + ascent (i in 0..timer_begin) Update(Interpolate_Smooth(0, 1, i / (timer_begin - 1))); + + loop (rand(30, 90)) Update(1); + + let timer_end = floor(rand(10, 30 + 1)); + descent (i in 0..timer_end) Update(Interpolate_Smooth(0, 1, i / (timer_end - 1))); + + function Update(mul_scale) { + //Sets up instance data. + ObjParticleList_SetScale(obj, scale * mul_scale, scale * mul_scale, 1); + ObjParticleList_SetAngle(obj, 0, 0, z_angle); + ObjParticleList_SetPosition(obj, x, y, 1); + + //Submits the current data to an instance, cleared every frame. + ObjParticleList_AddInstance(obj); + + x += x_speed; + y += y_speed; + z_angle += z_add; + yield; + } + } +} + diff --git a/script/sample/SampleRC02.txt b/script/sample/SampleRC02.txt new file mode 100644 index 0000000..21f50ad --- /dev/null +++ b/script/sample/SampleRC02.txt @@ -0,0 +1,75 @@ +#TouhouDanmakufu[Stage] +#ScriptVersion[3] +#Title["SampleRC02"] +#Text["SampleRC02: Particle Rendering (Custom Shader)"] + +@Initialize { + TSample(); +} + +@MainLoop { + yield; +} + +task TSample() { + let dir = GetCurrentScriptDirectory(); + + let obj = ObjParticleList_Create(OBJ_PARTICLE_LIST_2D); + + Obj_SetRenderPriorityI(obj, 21); + ObjPrim_SetTexture(obj, dir ~ "Effect01.png"); + + ObjRender_SetBlendType(obj, BLEND_ADD_ARGB); + + //You may also treat a 2D particle list object as a 2D sprite object. + ObjSprite2D_SetSourceRect(obj, 140, 39, 186, 86); + ObjSprite2D_SetDestCenter(obj); + + //This is absolutely necessary, rendering will not be performed otherwise. + ObjPrim_SetVertexIndex(obj, [0, 1, 2, 3]); + + ObjShader_SetShaderF(obj, dir ~ "SampleRC02_HLSL.txt"); + ObjShader_SetTechnique(obj, "Render"); + + loop { + CreateParticle(); + yield; + } + + task CreateParticle() { + let x = rand(0, 384); + let y = rand(0, 448); + let x_speed = rand(-1, 1); + let y_speed = rand(-1, 1); + let z_angle = rand(0, 360); + let z_add = rand(-5, 5); + let scale = rand(0.3, 0.7); + + let timer_begin = floor(rand(10, 30 + 1)); + ascent (i in 0..timer_begin) Update(Interpolate_Smooth(0, 1, i / (timer_begin - 1))); + + loop (rand(30, 90)) Update(1); + + let timer_end = floor(rand(10, 30 + 1)); + descent (i in 0..timer_end) Update(Interpolate_Smooth(0, 1, i / (timer_end - 1))); + + function Update(mul_scale) { + //Sets up instance data. + ObjParticleList_SetScale(obj, scale * mul_scale, scale * mul_scale, 1); + ObjParticleList_SetAngle(obj, 0, 0, z_angle); + ObjParticleList_SetPosition(obj, x, y, 1); + + //Three slots are provided. You may put anything here, as long as they are floats. + ObjParticleList_SetExtraData(obj, y / 448, 0, 0); + + //Submits the current data to an instance, cleared every frame. + ObjParticleList_AddInstance(obj); + + x += x_speed; + y += y_speed; + z_angle += z_add; + yield; + } + } +} + diff --git a/script/sample/SampleRC02_HLSL.txt b/script/sample/SampleRC02_HLSL.txt new file mode 100644 index 0000000..b7c61c6 --- /dev/null +++ b/script/sample/SampleRC02_HLSL.txt @@ -0,0 +1,81 @@ +sampler samp0_ : register(s0); + +//The 4-by-4 matrix linked to WORLDVIEWPROJ semantic is provided by the engine. +// It is used to transform world coordinates to device coordinates. +float4x4 g_mWorldViewProj : WORLDVIEWPROJ : register(c0); + +struct VS_INPUT { + //Vertex data + float4 position : POSITION; + float4 diffuse : COLOR0; + float2 texCoord : TEXCOORD0; + + //Instance data + float4 i_color : COLOR1; + float4 i_xyz_pos_x_scale : TEXCOORD1; //Pack: (x pos, y pos, z pos, x scale) + float4 i_yz_scale_xy_ang : TEXCOORD2; //Pack: (y scale, z scale, x angle, y angle) + float4 i_z_ang_extra : TEXCOORD3; //Pack: (z angle, extra 1, extra 2, extra 3) +}; +struct PS_INPUT { + float4 position : POSITION; + float4 diffuse : COLOR0; + float2 texCoord : TEXCOORD0; + float exAlpha : FOG; +}; + +PS_INPUT mainVS(VS_INPUT inVs) { + PS_INPUT outVs; + + float3 t_scale = float3(inVs.i_xyz_pos_x_scale.w, inVs.i_yz_scale_xy_ang.xy); + + float2 ax = float2(sin(inVs.i_yz_scale_xy_ang.z), cos(inVs.i_yz_scale_xy_ang.z)); + float2 ay = float2(sin(inVs.i_yz_scale_xy_ang.w), cos(inVs.i_yz_scale_xy_ang.w)); + float2 az = float2(sin(inVs.i_z_ang_extra.x), cos(inVs.i_z_ang_extra.x)); + + //Creates the transformation matrix. + float4x4 matInstance = float4x4( + float4( + t_scale.x * (ay.y * az.y - ax.x * ay.x * az.x), + t_scale.x * (-ax.y * az.x), + t_scale.x * (ay.x * az.y + ax.x * ay.y * az.x), + 0 + ), + float4( + t_scale.y * (ay.y * az.x + ax.x * ay.x * az.y), + t_scale.y * (ax.y * az.y), + t_scale.y * (ay.x * az.x - ax.x * ay.y * az.y), + 0 + ), + float4( + t_scale.z * (-ax.y * ay.x), + t_scale.z * (ax.x), + t_scale.z * (ax.y * ay.y), + 0 + ), + float4(inVs.i_xyz_pos_x_scale.x, inVs.i_xyz_pos_x_scale.y, inVs.i_xyz_pos_x_scale.z, 1) + ); + + outVs.diffuse = inVs.diffuse * inVs.i_color; + outVs.texCoord = inVs.texCoord; + outVs.position = mul(inVs.position, matInstance); + outVs.position = mul(outVs.position, g_mWorldViewProj); + outVs.position.z = 1.0f; + outVs.exAlpha = saturate(inVs.i_z_ang_extra.y); + + return outVs; +} + +float4 mainPS(PS_INPUT inPs) : COLOR0 { + float4 color = tex2D(samp0_, inPs.texCoord) * inPs.diffuse; + color.a *= inPs.exAlpha; + + return color; +} + +technique Render { + pass P0 { + VertexShader = compile vs_2_0 mainVS(); + PixelShader = compile ps_3_0 mainPS(); + } +} + diff --git a/script/sample/SampleRC03.txt b/script/sample/SampleRC03.txt new file mode 100644 index 0000000..6e2b8a7 --- /dev/null +++ b/script/sample/SampleRC03.txt @@ -0,0 +1,87 @@ +#TouhouDanmakufu[Stage] +#ScriptVersion[3] +#Title["SampleRC03"] +#Text["SampleRC03: Particle Rendering (Custom Shader, 3D)"] + +@Initialize { + SetFogParam(256, 1000, 0, 0, 0); + + TSample(); +} + +@MainLoop { + yield; +} + +task TSample() { + let dir = GetCurrentScriptDirectory(); + + let obj = ObjParticleList_Create(OBJ_PARTICLE_LIST_3D); + + Obj_SetRenderPriorityI(obj, 21); + ObjPrim_SetTexture(obj, dir ~ "Effect01.png"); + + ObjRender_SetBlendType(obj, BLEND_ADD_ARGB); + + //You may treat a 3D particle list object as either a 3D primitive object or a 3D sprite object. + ObjSprite3D_SetSourceRect(obj, 140, 39, 186, 86); + ObjSprite3D_SetDestRect(obj, -46 / 2, -47 / 2, 46 / 2, 47 / 2); + + //This is absolutely necessary, rendering will not be performed otherwise. + ObjPrim_SetVertexIndex(obj, [0, 1, 2, 3]); + + ObjShader_SetShaderF(obj, dir ~ "SampleRC03_HLSL.txt"); + ObjShader_SetTechnique(obj, "Render"); + + loop { + loop (7) CreateParticle(); + yield; + } + + task CreateParticle() { + let x = rand(-700, 700); + let y = rand(-700, 700); + let z = rand(-700, 700); + + let x_speed = rand(-2, 2); + let y_speed = rand(-2, 2); + let z_speed = rand(-2, 2); + + let x_angle = rand(0, 360); + let y_angle = rand(0, 360); + let z_angle = rand(0, 360); + let x_add = rand(-5, 5); + let y_add = rand(-5, 5); + let z_add = rand(-5, 5); + + let scale = rand(0.3, 0.7); + + let timer_begin = floor(rand(10, 30 + 1)); + ascent (i in 0..timer_begin) Update(Interpolate_Smooth(0, 1, i / (timer_begin - 1))); + + loop (rand(30, 90)) Update(1); + + let timer_end = floor(rand(10, 30 + 1)); + descent (i in 0..timer_end) Update(Interpolate_Smooth(0, 1, i / (timer_end - 1))); + + function Update(mul_scale) { + //Sets up instance data. + let tmp_sc = scale * mul_scale; + ObjParticleList_SetScale(obj, tmp_sc, tmp_sc, tmp_sc); + ObjParticleList_SetAngle(obj, x_angle, y_angle, z_angle); + ObjParticleList_SetPosition(obj, x, y, z); + + //Submits the current data to an instance, cleared every frame. + ObjParticleList_AddInstance(obj); + + x += x_speed; + y += y_speed; + z += z_speed; + x_angle += x_add; + y_angle += y_add; + z_angle += z_add; + yield; + } + } +} + diff --git a/script/sample/SampleRC03_HLSL.txt b/script/sample/SampleRC03_HLSL.txt new file mode 100644 index 0000000..d734665 --- /dev/null +++ b/script/sample/SampleRC03_HLSL.txt @@ -0,0 +1,108 @@ +sampler samp0_ : register(s0); + +//The following semantic-linked global variables are provided by the engine. +// WORLD (float4x4) +// The camera matrix. This can be ignored when the particle lists are not intended to be billboarded. +// VIEW (float4x4) +// The view matrix. Used to transform world coordinates to camera coordinates. +// PROJECTION (float4x4) +// The projection matrix. Used to transform camera coordinates to device coordinates. +// FOGENABLE (bool) +// A boolean indicating whether fog was enabled for the particle list object. +// FOGCOLOR (float4) +// The color of the fog set with SetFogParam. The packing format is (r, g, b, a). +// FOGDIST (float2) +// The ranges of the fog set with SetFogParam. The packing format is (fog start, fog end). +float4x4 g_mCamera : WORLD : register(c0); +float4x4 g_mView : VIEW : register(c4); +float4x4 g_mProj : PROJECTION : register(c8); +bool g_bUseFog : FOGENABLE : register(b0) = false; +float4 g_vFogColor : FOGCOLOR : register(c12) = float4(0.0f, 0.0f, 0.0f, 0.0f); +float2 g_vFogDist : FOGDIST : register(c13) = float2(0.0f, 256.0f); + +struct VS_INPUT { + //Vertex data + float4 position : POSITION; + float4 diffuse : COLOR0; + float2 texCoord : TEXCOORD0; + + //Instance data + float4 i_color : COLOR1; + float4 i_xyz_pos_x_scale : TEXCOORD1; //Pack: (x pos, y pos, z pos, x scale) + float4 i_yz_scale_xy_ang : TEXCOORD2; //Pack: (y scale, z scale, x angle, y angle) + float4 i_z_ang_extra : TEXCOORD3; //Pack: (z angle, extra 1, extra 2, extra 3) +}; +struct PS_INPUT { + float4 position : POSITION; + float4 diffuse : COLOR0; + float2 texCoord : TEXCOORD0; + float fogBlend : FOG; +}; + +PS_INPUT mainVS(VS_INPUT inVs) { + PS_INPUT outVs; + + float3 t_scale = float3(inVs.i_xyz_pos_x_scale.w, inVs.i_yz_scale_xy_ang.xy); + + float2 ax = float2(sin(inVs.i_yz_scale_xy_ang.z), cos(inVs.i_yz_scale_xy_ang.z)); + float2 ay = float2(sin(inVs.i_yz_scale_xy_ang.w), cos(inVs.i_yz_scale_xy_ang.w)); + float2 az = float2(sin(inVs.i_z_ang_extra.x), cos(inVs.i_z_ang_extra.x)); + + //Creates the transformation matrix. + //Calculate positions later after transformation with g_mCamera. Necessary for billboarded sprites to render correctly. + float4x4 matInstance = float4x4( + float4( + t_scale.x * (ay.y * az.y - ax.x * ay.x * az.x), + t_scale.x * (-ax.y * az.x), + t_scale.x * (ay.x * az.y + ax.x * ay.y * az.x), + 0 + ), + float4( + t_scale.y * (ay.y * az.x + ax.x * ay.x * az.y), + t_scale.y * (ax.y * az.y), + t_scale.y * (ay.x * az.x - ax.x * ay.y * az.y), + 0 + ), + float4( + t_scale.z * (-ax.y * ay.x), + t_scale.z * (ax.x), + t_scale.z * (ax.y * ay.y), + 0 + ), + float4(0, 0, 0, 1) + ); + + outVs.diffuse = inVs.diffuse * inVs.i_color; + outVs.texCoord = inVs.texCoord; + + outVs.position = mul(inVs.position, matInstance); + outVs.position = mul(outVs.position, g_mCamera); + //After billboarding has been accounted for, add the instance positions. + outVs.position.xyz += inVs.i_xyz_pos_x_scale.xyz; + outVs.position = mul(outVs.position, g_mView); + + //Compute fog while the position is in camera space. + if (g_bUseFog) + outVs.fogBlend = saturate((g_vFogDist.y - outVs.position.z) / (g_vFogDist.y - g_vFogDist.x)); + + outVs.position = mul(outVs.position, g_mProj); + + return outVs; +} + +float4 mainPS(PS_INPUT inPs) : COLOR0 { + float4 color = tex2D(samp0_, inPs.texCoord); + + if (g_bUseFog) + color.rgb = lerp(g_vFogColor.rgb, color.rgb, inPs.fogBlend); + + return (color * inPs.diffuse); +} + +technique Render { + pass P0 { + VertexShader = compile vs_3_0 mainVS(); + PixelShader = compile ps_3_0 mainPS(); + } +} + diff --git a/script/sample/SampleVS01.txt b/script/sample/SampleVS01.txt new file mode 100644 index 0000000..b9dcfb6 --- /dev/null +++ b/script/sample/SampleVS01.txt @@ -0,0 +1,64 @@ +#TouhouDanmakufu[Stage] +#ScriptVersion[3] +#Title["SampleVS01"] +#Text["SampleVS01: Basic Vertex Shaders"] + +@Initialize { + TSample(); +} + +@MainLoop { + if (GetKeyState(KEY_Q) == KEY_PUSH) + CloseStgScene(); + yield; +} + +task TSample() { + let dir = GetCurrentScriptDirectory(); + let path = dir ~ "../default_system/img/Default_Background_IceMountain_Spell01.png"; + + let obj = ObjPrim_Create(OBJ_PRIMITIVE_2D); + Obj_SetRenderPriorityI(obj, 23); + ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLESTRIP); + ObjPrim_SetTexture(obj, path); + + //Please do not actually use 10000 vertices + let VC = 5000; + + ObjPrim_SetVertexCount(obj, VC * 2); + ObjRender_SetPosition(obj, 192, 224, 1); + + ascent (i in 0..VC) { + let v_angle = 360 / (VC - 1) * i; + let tex_v = 1 / (VC - 1) * i; + ObjPrim_SetVertexPosition(obj, i * 2, 0, 0, 1); + ObjPrim_SetVertexPosition(obj, i * 2 + 1, 240 * cos(v_angle), 240 * sin(v_angle), 1); + ObjPrim_SetVertexUV(obj, i * 2, 0, tex_v); + ObjPrim_SetVertexUV(obj, i * 2 + 1, 1, tex_v); + } + + //Enables vertex shader rendering. + //If this is set to true and a vertex+pixel shader isn't used, rendering will always fail. + ObjRender_SetVertexShaderRenderingMode(obj, true); + + ObjShader_SetShaderF(obj, dir ~ "SampleVS01_HLSL.txt"); + ObjShader_SetTechnique(obj, "Render"); + + let t = 0; + while (true) { + ObjShader_SetFloat(obj, "frame_", t); + /* + //Equivalent to these + ascent(i in 0..VC){ + let tex_v = 1 / (VC - 1) * i; + ObjPrim_SetVertexUV(obj, i * 2, 0 - t, tex_v); + ObjPrim_SetVertexUV(obj, i * 2 + 1, 1 - t, tex_v); + } + */ + + t += 0.006; + t %= 1; + yield; + } +} + diff --git a/script/sample/SampleVS01_HLSL.txt b/script/sample/SampleVS01_HLSL.txt new file mode 100644 index 0000000..f94f62d --- /dev/null +++ b/script/sample/SampleVS01_HLSL.txt @@ -0,0 +1,53 @@ +sampler samp0_ : register(s0); + +//2 top-level semantics are provided by the engine in the case of 2D render objects: +// WORLD: +// Contains the transformation matrix of the render object. +// VIEWPROJECTION: +// Contains the projection*camera matrix, used for correctly tranforming vertices to screen-space coordinates. +float4x4 g_mWorld : WORLD; +float4x4 g_mViewProj : VIEWPROJECTION; + +float frame_; + +struct VS_INPUT { + float4 position : POSITION; + float4 diffuse : COLOR0; + float2 texCoord : TEXCOORD0; +}; +struct PS_INPUT { + float4 position : POSITION; + float4 diffuse : COLOR0; + float2 texCoord : TEXCOORD0; +}; +struct PS_OUTPUT { + float4 color : COLOR0; +}; + +PS_INPUT mainVS(VS_INPUT inVs) { + PS_INPUT outVs; + + outVs.diffuse = inVs.diffuse; + outVs.texCoord = inVs.texCoord; + outVs.position = mul(inVs.position, g_mWorld); + outVs.position = mul(outVs.position, g_mViewProj); + outVs.position.z = 1.0f; + + return outVs; +} + +PS_OUTPUT mainPS(PS_INPUT inPs) { + PS_OUTPUT outPs; + + outPs.color = tex2D(samp0_, inPs.texCoord - float2(frame_, 0)) * inPs.diffuse; + + return outPs; +} + +technique Render { + pass P0 { + VertexShader = compile vs_2_0 mainVS(); + PixelShader = compile ps_2_0 mainPS(); + } +} + diff --git a/script/sample/SampleVS02.txt b/script/sample/SampleVS02.txt new file mode 100644 index 0000000..94b68b2 --- /dev/null +++ b/script/sample/SampleVS02.txt @@ -0,0 +1,164 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["SampleVS02"] +#Text["SampleVS02: Vertex Shader-Based Distortion Effect"] +#Background["script/default_system/Default_Background_IceMountain.txt"] + +#include "script/default_system/Default_ShotConst.txt" + +let objEnemy; +let objPlayer; +let frame = 0; + +@Event { + alternative(GetEventType()) + case(EV_REQUEST_LIFE) { + SetScriptResult(500); + } +} + +@Initialize { + objPlayer = GetPlayerObjectID(); + + objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS); + ObjEnemy_Regist(objEnemy); + + let imgExRumia = GetCurrentScriptDirectory ~ "ExRumia.png"; + ObjPrim_SetTexture(objEnemy, imgExRumia); + ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(objEnemy); + + let cx = GetStgFrameWidth() / 2; + ObjMove_SetDestAtFrame(objEnemy, cx, 180, 60); + + TWaveCircle(); + TFinalize(); +} + +@MainLoop { + let ex = ObjMove_GetX(objEnemy); + let ey = ObjMove_GetY(objEnemy); + + if (frame == 120) { + let px = GetPlayerX(); + ObjMove_SetDestAtFrame(objEnemy, rand(192 - 80, 192 + 80), rand(100, 230), 40); + //ObjMove_SetDestAtFrame(objEnemy, 0, rand(120, 300), 40); + + frame = 0; + } + + ObjEnemy_SetIntersectionCircleToShot(objEnemy, ex, ey, 32); + + frame++; + yield; +} + +task TWaveCircle() { + wait(60); + + let color = [1, 0.065, 0.065]; + let renderTexture = GetReservedRenderTargetName(0); + + let stripWave = []; + + let countEdge = 32; + let countStrip = 4; + let maxRadius = 128; + + let frameLeft = GetStgFrameLeft(); + let frameTop = GetStgFrameTop(); + + let objWave = ObjPrim_Create(OBJ_PRIMITIVE_2D); + + Obj_SetRenderPriorityI(objWave, 26); + ObjPrim_SetPrimitiveType(objWave, PRIMITIVE_TRIANGLELIST); + ObjPrim_SetTexture(objWave, renderTexture); + + ObjPrim_SetVertexCount(objWave, countEdge * countStrip * 6); + + ascent (i in 0..countStrip) { + let stripWidth = maxRadius / (countStrip - 1); + let rInEdge = stripWidth * i; + FillRingVertex(i * countEdge * 6, rInEdge, rInEdge + stripWidth); + } + + ObjRender_SetVertexShaderRenderingMode(objWave, true); + ObjShader_SetShaderF(objWave, GetCurrentScriptDirectory() ~ "SampleVS02_HLSL.txt"); + ObjShader_SetTechnique(objWave, "Render"); + + let ex = ObjMove_GetX(objEnemy); + let ey = ObjMove_GetY(objEnemy); + + let nowRadius = 0; + + let t = 0; + while (!Obj_IsDeleted(objEnemy)) { + ex = ObjMove_GetX(objEnemy); + ey = ObjMove_GetY(objEnemy); + + if(nowRadius < maxRadius){ + let tmp = sin((t + 1) / 50 * 90); + nowRadius = maxRadius * tmp; + } + + Update(); + } + { + let _radius = nowRadius; + + descent(i in 0..30){ + let tmp = sin((i + 1) / 30 * 90); + nowRadius = _radius * tmp; + + Update(); + } + } + + Obj_Delete(objWave); + + function Update() { + RenderToTextureA1(renderTexture, 20, 25, true); + + ObjShader_SetFloat(objWave, "frame_", t); + ObjShader_SetFloat(objWave, "waveSine_", 0.8 + sin(t * 5) * 0.5); + ObjShader_SetFloatArray(objWave, "waveRadius_", [nowRadius, maxRadius]); + + ObjShader_SetFloatArray(objWave, "enemyPos_", [ex + frameLeft, ey + frameTop]); + ObjShader_SetFloatArray(objWave, "waveColor_", color); + + //ObjRender_SetPosition(objWave, ex, ey, 1); + + t++; + yield; + } + + function FillRingVertex(vi_start, r_inner, r_outer) { + ascent (i in 0..countEdge) { + let vi = vi_start + i * 6; + let v_angle = 360 / (countEdge - 1); + let s1 = sin(v_angle * i); + let c1 = cos(v_angle * i); + let s2 = sin(v_angle * (i + 1)); + let c2 = cos(v_angle * (i + 1)); + ObjPrim_SetVertexPosition(objWave, vi + 0, r_inner * c1, r_inner * s1, 1); + ObjPrim_SetVertexPosition(objWave, vi + 1, r_outer * c1, r_outer * s1, 1); + ObjPrim_SetVertexPosition(objWave, vi + 2, r_inner * c2, r_inner * s2, 1); + ObjPrim_SetVertexPosition(objWave, vi + 3, r_outer * c1, r_outer * s1, 1); + ObjPrim_SetVertexPosition(objWave, vi + 4, r_inner * c2, r_inner * s2, 1); + ObjPrim_SetVertexPosition(objWave, vi + 5, r_outer * c2, r_outer * s2, 1); + ObjPrim_SetVertexUVT(objWave, vi + 0, r_inner * c1, r_inner * s1); + ObjPrim_SetVertexUVT(objWave, vi + 1, r_outer * c1, r_outer * s1); + ObjPrim_SetVertexUVT(objWave, vi + 2, r_inner * c2, r_inner * s2); + ObjPrim_SetVertexUVT(objWave, vi + 3, r_outer * c1, r_outer * s1); + ObjPrim_SetVertexUVT(objWave, vi + 4, r_inner * c2, r_inner * s2); + ObjPrim_SetVertexUVT(objWave, vi + 5, r_outer * c2, r_outer * s2); + } + } +} + +task TFinalize(){ + while (ObjEnemy_GetInfo(objEnemy, INFO_LIFE) > 0) { yield; } + Obj_Delete(objEnemy); + wait(120); + CloseScript(GetOwnScriptID()); +} \ No newline at end of file diff --git a/script/sample/SampleVS02_HLSL.txt b/script/sample/SampleVS02_HLSL.txt new file mode 100644 index 0000000..97be4c9 --- /dev/null +++ b/script/sample/SampleVS02_HLSL.txt @@ -0,0 +1,80 @@ +sampler samp0_ : register(s0); + +//2 top-level semantics are provided by the engine in the case of 2D render objects: +// WORLD: +// Contains the transformation matrix of the render object. +// VIEWPROJECTION: +// Contains the projection*camera matrix, used for correctly tranforming vertices to screen-space coordinates. +float4x4 g_mViewProj : VIEWPROJECTION; + +float frame_; +float2 waveRadius_; +float waveSine_; +float2 enemyPos_; +float2 framePos_; +float3 waveColor_; + +static const float RENDER_LEFT = 32.5f / 1024.0f; //mininum render width +static const float RENDER_TOP = 16.5f / 512.0f; //maximum render width +static const float RENDER_RIGHT = 415.5f / 1024.0f; //mininum render height +static const float RENDER_BOTTOM = 463.5f / 512.0f; //maximum render height +static const float2 SCREEN_SPACE = float2(1024.0f, 512.0f); + +struct VS_INPUT { + float4 position : POSITION; + float4 diffuse : COLOR0; + float2 texCoord : TEXCOORD0; +}; +struct PS_INPUT { + float4 position : POSITION; + float4 diffuse : COLOR0; + float2 texCoord : TEXCOORD0; + float blend : FOG; +}; +struct PS_OUTPUT { + float4 color : COLOR0; +}; + +PS_INPUT mainVS(VS_INPUT inVs) { + PS_INPUT outVs; + + float mul_scale = waveRadius_.x / waveRadius_.y; + float2 posVertex = inVs.position.xy * mul_scale; + + float dist = length(inVs.position.xy * mul_scale); + outVs.blend = saturate((waveRadius_.x - dist) / waveRadius_.x); + + float2 cos_sin = posVertex.xy / dist; + float2 distortPos = cos_sin.xy * waveRadius_.x * min(outVs.blend, 0.22f) * 0.5f * waveSine_; + distortPos.x += (cos_sin.x * outVs.blend) * 16.0f; + distortPos.y += (cos_sin.y * outVs.blend) * 16.0f; + + outVs.texCoord = inVs.texCoord * mul_scale + enemyPos_ / SCREEN_SPACE; + outVs.position = mul(float4(posVertex + enemyPos_ + distortPos, inVs.position.zw), g_mViewProj); + outVs.position.zw = (float2)1.0f; + outVs.diffuse = inVs.diffuse; + + return outVs; +} + +PS_OUTPUT mainPS(PS_INPUT inPs) { + PS_OUTPUT outPs; + + inPs.texCoord.x = clamp(inPs.texCoord.x, RENDER_LEFT, RENDER_RIGHT); + inPs.texCoord.y = clamp(inPs.texCoord.y, RENDER_TOP, RENDER_BOTTOM); + + float3 colorRGB = tex2D(samp0_, inPs.texCoord).rgb; + colorRGB.rgb -= (1.0f - waveColor_.xyz) * inPs.blend; + + outPs.color = float4(colorRGB, 1.0f) * inPs.diffuse; + + return outPs; +} + +technique Render { + pass P0 { + VertexShader = compile vs_3_0 mainVS(); + PixelShader = compile ps_3_0 mainPS(); + } +} + diff --git a/script/sample/SampleVS03.txt b/script/sample/SampleVS03.txt new file mode 100644 index 0000000..2c4e617 --- /dev/null +++ b/script/sample/SampleVS03.txt @@ -0,0 +1,74 @@ +#TouhouDanmakufu[Stage] +#ScriptVersion[3] +#Title["SampleVS03"] +#Text["SampleVS03: Basic Vertex Shaders (3D)"] + +@Initialize { + SetCameraFocusX(0); + SetCameraFocusY(0); + SetCameraFocusZ(0); + SetCameraRadius(800); + SetCameraElevationAngle(35); + SetCameraAzimuthAngle(0); + + SetFogParam(0, 768, 64, 0, 0); + + TSample(); +} + +@MainLoop { + if (GetKeyState(KEY_Q) == KEY_PUSH) + CloseStgScene(); + yield; +} + +task TSample() { + let dir = GetCurrentScriptDirectory(); + let path = dir ~ "../default_system/img/Default_Background_IceMountain_Spell01.png"; + + let obj = ObjPrim_Create(OBJ_PRIMITIVE_3D); + Obj_SetRenderPriorityI(obj, 22); + ObjPrim_SetPrimitiveType(obj, PRIMITIVE_TRIANGLESTRIP); + ObjPrim_SetTexture(obj, path); + + let VC = 5000; + + ObjPrim_SetVertexCount(obj, VC * 2); + ObjRender_SetPosition(obj, 320, 240, 1); + + ascent (i in 0..VC) { + let v_angle = 360 / (VC - 1) * i; + let tex_v = 1 / (VC - 1) * i; + ObjPrim_SetVertexPosition(obj, i * 2, 0, 0, 1); + ObjPrim_SetVertexPosition(obj, i * 2 + 1, 256 * cos(v_angle), 256 * sin(v_angle), 1); + ObjPrim_SetVertexUV(obj, i * 2, 0, tex_v); + ObjPrim_SetVertexUV(obj, i * 2 + 1, 1, tex_v); + } + + //Enables vertex shader rendering. + //If this is set to true and a vertex+pixel shader isn't used, rendering will always fail. + ObjRender_SetVertexShaderRenderingMode(obj, true); + + ObjShader_SetShaderF(obj, dir ~ "SampleVS03_HLSL.txt"); + ObjShader_SetTechnique(obj, "Render"); + + let t = 0; + while (true) { + ObjRender_SetAngleX(obj, -90); + ObjRender_SetAngleZ(obj, t * 70); + + ObjShader_SetFloat(obj, "frame_", t); + /* + //Equivalent to these + ascent(i in 0..VC){ + let tex_v = 1 / (VC - 1) * i; + ObjPrim_SetVertexUV(obj, i * 2, 0 - t, tex_v); + ObjPrim_SetVertexUV(obj, i * 2 + 1, 1 - t, tex_v); + } + */ + + t += 0.003; + yield; + } +} + diff --git a/script/sample/SampleVS03_HLSL.txt b/script/sample/SampleVS03_HLSL.txt new file mode 100644 index 0000000..40e4a53 --- /dev/null +++ b/script/sample/SampleVS03_HLSL.txt @@ -0,0 +1,64 @@ +sampler sampler0_ : register(s0); + +//The following semantic-linked global variables are provided by the engine. +// WORLD (float4x4) +// The transformation matrix of the render object. +// VIEW (float4x4) +// The view matrix. Used to transform world coordinates to camera coordinates. +// PROJECTION (float4x4) +// The projection matrix. Used to transform camera coordinates to device coordinates. +// FOGENABLE (bool) +// A boolean indicating whether fog was enabled for the render object. +// FOGCOLOR (float4) +// The color of the fog set with SetFogParam. The packing format is (r, g, b, a). +// FOGDIST (float2) +// The ranges of the fog set with SetFogParam. The packing format is (fog start, fog end). + +float4x4 g_mWorld : WORLD : register(c0); +float4x4 g_mView : VIEW : register(c4); +float4x4 g_mProj : PROJECTION : register(c8); + +float4 g_vFogColor : FOGCOLOR : register(c12); +float2 g_vFogDist : FOGDIST : register(c13); + +float frame_; + +struct VS_INPUT { + float4 position : POSITION; + float4 diffuse : COLOR0; + float2 texCoord : TEXCOORD0; +}; +struct VS_OUTPUT { + float4 position : POSITION; + float4 diffuse : COLOR0; + float2 texCoord : TEXCOORD0; + float fog : FOG; +}; + +VS_OUTPUT mainVS(VS_INPUT InVs) { + VS_OUTPUT OutVs; + + OutVs.diffuse = InVs.diffuse; + OutVs.texCoord = InVs.texCoord - float2(frame_, 0); + OutVs.position = mul(InVs.position, g_mWorld); + OutVs.position = mul(OutVs.position, g_mView); + + OutVs.fog = saturate((g_vFogDist.y - OutVs.position.z) / (g_vFogDist.y - g_vFogDist.x)); + + OutVs.position = mul(OutVs.position, g_mProj); + + return OutVs; +} + +float4 mainPS(VS_OUTPUT InPs) : COLOR0 { + float4 color = tex2D(sampler0_, InPs.texCoord); + color.rgb = lerp(g_vFogColor.rgb, color.rgb, InPs.fog); + return color * InPs.diffuse; +} + +technique Render { + pass P0 { + VertexShader = compile vs_3_0 mainVS(); + PixelShader = compile ps_3_0 mainPS(); + } +} \ No newline at end of file diff --git a/th_dnh.def b/th_dnh.def new file mode 100644 index 0000000..109ba9b --- /dev/null +++ b/th_dnh.def @@ -0,0 +1,35 @@ +//-------------------------------------------------------------- +//Package Script Path +// Upon starting the game, the specified package script will be run. +package.script.main = script/GayGunner_Package.dnh + +//-------------------------------------------------------------- +//Window Title +// The text to display on the window title. +//window.title = gaming + +//-------------------------------------------------------------- +//Screen Size +// The default size is 640x480, use these parameters to change the screen size. +// Minimum and maximum size is 320x240 and 1920x1200 respectively. +screen.width = 1280 +screen.height = 720 + +//-------------------------------------------------------------- +//Window Size List +// The sizes that will be listed in config.exe's Window Size drop-down panel. +// Separated with whitespaces or incorrect size formats. +window.size.list = 960x540 1280x720 1920x1080 + +//-------------------------------------------------------------- +//Skip Mode Speed +// The speed multiplier of the skip mode. (Triggered while Left CTRL is held down by default.) +// Limited between 1 and 50. +skip.rate = 20 + +//-------------------------------------------------------------- +//Enable/Disable Unfocused Processing +// When set to true, enables the engine to continue running in the background +// even if the user has clicked off the window, or if the window is minimized. +// Also enables notifications of EV_APP_LOSE_FOCUS and EV_APP_RESTORE_FOCUS. +unfocused.processing = false \ No newline at end of file diff --git a/th_dnh_ph3sx.exe b/th_dnh_ph3sx.exe new file mode 100644 index 0000000..a977270 Binary files /dev/null and b/th_dnh_ph3sx.exe differ diff --git a/th_dnh_ph3sx_legacy.exe b/th_dnh_ph3sx_legacy.exe new file mode 100644 index 0000000..3994b7e Binary files /dev/null and b/th_dnh_ph3sx_legacy.exe differ diff --git a/tools/FileArchiver.exe b/tools/FileArchiver.exe new file mode 100644 index 0000000..e181c2f Binary files /dev/null and b/tools/FileArchiver.exe differ diff --git a/tools/FileArchiver_readme.txt b/tools/FileArchiver_readme.txt new file mode 100644 index 0000000..dcedd50 --- /dev/null +++ b/tools/FileArchiver_readme.txt @@ -0,0 +1,3 @@ +● What's This? + The FileArchiver is a tool to create encrypted archives. + Archives made with ph3sx's FileArchiver are not compatible with vanilla ph3. \ No newline at end of file