diff --git a/LogWindow.dat b/LogWindow.dat new file mode 100644 index 0000000..a508efe Binary files /dev/null and b/LogWindow.dat differ 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/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/3drender/3dtimebicht.dnh b/script/3drender/3dtimebicht.dnh new file mode 100644 index 0000000..8ca842b --- /dev/null +++ b/script/3drender/3dtimebicht.dnh @@ -0,0 +1,187 @@ +// 3D STAGE TUTORIAL + +// X : horizontal, Y : vertical, Z : depth (close/near) + +// Stage script -> Set textures + +#TouhouDanmakufu[Stage] +#Title["3D Stages"] +#Text["Stage script for 3D practice"] +#ScriptVersion[3] +#System["script/KevinSystem/Kevin_System.txt"] + +let CSD = GetCurrentScriptDirectory; +let texturefloor = CSD ~ "sprite/dafloorEX.png"; +let texturewall = CSD ~ "sprite/damagicwall.png"; +let texturefog = CSD ~ "sprite/cardbg4.png"; + +// REMEMBER : set variable texturefloor as png because my ass internet +// can't download a simple png + +// ------- Function to create one floor piece -------// + +/* +SetAngleXYZ? + ++ Rotates/flips the 3D sprite around a X, Y, Z axis. ++ Direction is influenced by HOW THE CAMERA IS SET -> Setting the camera +correctly is important! + +X : horizontal +Y : vertical +Z : depth + +*/ + +function FloorCreation(locX,locY,locZ){ + let floorObj = ObjPrim_Create(OBJ_SPRITE_3D); + ObjPrim_SetTexture(floorObj,texturefloor); + Obj_SetRenderPriorityI(floorObj,20); + ObjSprite3D_SetSourceDestRect(floorObj,0,0,512,512); + ObjRender_SetScaleXYZ(floorObj,1,1,0); + ObjRender_SetZWrite(floorObj,true); + + ObjRender_SetAngleXYZ(floorObj,90,0,0); // Floor-styled render + + ObjRender_SetPosition(floorObj,locX,locY,locZ); // Positioning of floor, notice function parameters +} + +function WallCreation(locX,locY,locZ){ + let floorObj = ObjPrim_Create(OBJ_SPRITE_3D); + ObjPrim_SetTexture(floorObj,texturewall); + Obj_SetRenderPriorityI(floorObj,20); + ObjSprite3D_SetSourceDestRect(floorObj,0,0,1024,1024); + ObjRender_SetScaleXYZ(floorObj,0.5,1,0); + ObjRender_SetZWrite(floorObj,true); + + ObjRender_SetAngleXYZ(floorObj,0,90,0); // Wall-styled render + + ObjRender_SetPosition(floorObj,locX,locY,locZ); + +} + +function FogCreation(locX,locY,locZ){ + let floorObj = ObjPrim_Create(OBJ_SPRITE_3D); + ObjPrim_SetTexture(floorObj,texturefog); + Obj_SetRenderPriorityI(floorObj,20); + ObjSprite3D_SetSourceDestRect(floorObj,0,0,1024,1024); // Fully covers screen + ObjRender_SetScaleXYZ(floorObj,4,4,0); + ObjRender_SetZWrite(floorObj,true); + + // ObjRender_SetAngleXYZ(floorObj,0,0,0); -> NOT USED, + // as the fog will always be facing player + + ObjSprite3D_SetBillboard(floorObj,true); + ObjRender_SetPosition(floorObj,locX,locY,locZ); + +} + +@Initialize{ + // Call the task to start stage renders + //SetIntersectionVisualization(true); + StageTime; + scrollitbabe; +} + +@Event{ + +} + +@MainLoop{ + yield; +} + +@Finalize{ + +} + +task StageTime{ + + // Fog construction + SetFogEnable(true); + SetFogParam(1024,1536,20,15,35); + FogCreation(0,0,2048); + + // Stage construction, like cardboard house building + ascent(i in 0..4){ + FloorCreation(0,0,512*i); + yield; + } + ascent (i in 0..4){ + WallCreation(-256,256,512*i); + yield; + } + ascent (i in 0..4){ + WallCreation(256,256,512*i); + yield; + } + +} + +// Stage scrolling + +/* Guide : CAMERAS????? + +* AZIMUTH * + +SetCameraAzimuthAngle(0); - ????? +SetCameraElevationAngle(0); - How HIGH the camera is +SetCameraRadius(0); - How FAR the camera is + +* FOCUS * + +SetCameraFocusX(0); +SetCameraFocusY(0); +SetCameraFocusZ(0); + +* ????? * + +SetCameraYaw(0); +SetCameraPitch(0); +SetCameraRoll(0); +*/ +task scrollitbabe{ + let scroll = 0; + let ang = 0; + let theyaeur = -180; + // CAMERA SYSTEM handled here + + // Min/max camera render distance + SetCameraPerspectiveClip(16,6000); + + // Camera settings - TBE (to be explained) + async{ + loop{ + SetCameraAzimuthAngle(theyaeur); + theyaeur = Interpolate_Decelerate(-105, -115, cos(NormalizeAngle(ang))); + ang += 1; + yield; + } + } + + + SetCameraElevationAngle(15); + SetCameraRadius(64); + SetCameraFocusX(0); + SetCameraFocusY(512); + SetCameraFocusZ(-512); + + /* GUIDE : The scroll illusion + + Make a variable, add it to CameraZ + Count the variable to move CameraZ forward + At a certain point, reset it back to the beginning + Add fog, profit(?) */ + + loop{ + SetCameraFocusZ(-512+scroll); + if(scroll > 512){ + scroll = 0; + } + scroll+=24; + yield; + } + + // Maintaining the perfect illusion with Fog +} + diff --git a/script/3drender/all of these are taken from other scripts.txt b/script/3drender/all of these are taken from other scripts.txt new file mode 100644 index 0000000..e69de29 diff --git a/script/3drender/alright bestie learn these camera settings.PNG b/script/3drender/alright bestie learn these camera settings.PNG new file mode 100644 index 0000000..eda8172 Binary files /dev/null and b/script/3drender/alright bestie learn these camera settings.PNG differ diff --git a/script/3drender/simplicity_sakuraboogaloo.dnh b/script/3drender/simplicity_sakuraboogaloo.dnh new file mode 100644 index 0000000..39c1c27 --- /dev/null +++ b/script/3drender/simplicity_sakuraboogaloo.dnh @@ -0,0 +1,274 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["the fruit of your labors, part 1"] +#Text["ayyy lmao"] + +// Declaring variables + +// Boss positions + Boss graphic + Shot sheet + let bossObj; + let bossX = 0; //These are important + let bossY = 0; + + //Animation frames + let aniframe = 0; + let aniframe2 = 0; + + let imgBoss = "script/basic4/sprite/enm_yuyuko.png"; + let angleO = 90; + let wintery = "script/basic4/sprite/cardbg3.png"; + let sakura = "script/basic4/sprite/cardbg4.png"; + + let spellSFX = "script/basic4/sounds/cardstart.wav"; + let bossdefeatSFX = "script/basic4/sounds/bossdie.wav"; + + #include "script/default_system/Default_ShotConst.txt" // Shot sheet goes here, include DOES NOT include semicolon + #include "script/default_system/Default_Effect.txt" + +// Hell + +@Initialize { + + // Auto-delete objects when script ends + SetAutoDeleteObject(true); + + // Define a bossObj is boss, register into script + bossObj = ObjEnemy_Create(OBJ_ENEMY_BOSS); + ObjEnemy_Regist(bossObj); + + // Start position OUTSIDE playing bounds + ObjMove_SetPosition(bossObj,192,-100); + // Moving boss to x, y location at speed + ObjMove_SetDestAtSpeed(bossObj,192,120,4); + + // Load sounds + + LoadSound(spellSFX); + LoadSound(bossdefeatSFX); + + //Play sounds + + PlaySE(spellSFX); + + mainTask; +} + +@Event { + // Setting boss timer and life + alternative(GetEventType()) + + case(EV_REQUEST_LIFE) { + SetScriptResult(2500); + } + + case(EV_REQUEST_TIMER) { + SetScriptResult(30); + } + + case(EV_REQUEST_SPELL_SCORE) { + SetScriptResult(2500000); + } + +} + +//MainLoop - everything always happens, all the time +@MainLoop { + bossX = ObjMove_GetX(bossObj); + bossY = ObjMove_GetY(bossObj); + //The boss position is ALWAYS UPDATED + + // Collision for the shots and player + ObjEnemy_SetIntersectionCircleToShot(bossObj, bossX, bossY, 36); + ObjEnemy_SetIntersectionCircleToShot(bossObj, bossX, bossY, 18); + yield; // yielding mainloop tells the script to "look for other tasks" to perform +} + +@Finalize { + +} + +//Creating functions for simplicity +function wait(w) {loop(w) {yield;}} + +task mainTask { + renderBoss; + render; + BossMove; + ending; + shotyeet; +} + +// NEW : BACKGROUNDS AND SPELL OVERLAYS + +// Note : textures are objects + +task render { + let scrollTex = 0; + + // BG + let bgObj = ObjPrim_Create(OBJ_SPRITE_2D); + // NOTE : Obj_SetRenderPriorityI DIFFERENT FROM Obj_SetRenderPriority + Obj_SetRenderPriorityI(bgObj,20); + ObjPrim_SetTexture(bgObj,wintery); + ObjSprite2D_SetSourceRect(bgObj,0,0,512,512); + ObjSprite2D_SetDestRect(bgObj,0,0,GetStgFrameWidth,GetStgFrameHeight); + + // SPELL BG + let spellObj = ObjPrim_Create(OBJ_SPRITE_2D); + // RENDER PRIORITY NOTICE : OVERLAY ABOVE BG + Obj_SetRenderPriorityI(spellObj,21); + ObjPrim_SetTexture(spellObj,sakura); + ObjRender_SetBlendType(spellObj,BLEND_ADD_ARGB); // Blending option : ADDITIVE + Alpha + RGB (opacity + glow) + ObjRender_SetAlpha(spellObj,240); + ObjSprite2D_SetSourceRect(spellObj,0,0,1024,1024); + ObjSprite2D_SetDestRect(spellObj,0,0,GetStgFrameWidth,GetStgFrameHeight); + + // Scroll overlay while boss is alive + while(!Obj_IsDeleted(bossObj)){ + ObjSprite2D_SetSourceRect(spellObj,0-scrollTex,0-scrollTex,1024-scrollTex,1024-scrollTex); + scrollTex+=1; + yield; + } + Obj_Delete(spellObj); +} + +task fire { + let playerdir; + let newdir; + playerdir = GetAngleToPlayer(bossObj); + CreateShotA1(bossX,bossY,5,playerdir+10,55,5); + CreateShotA1(bossX,bossY,5,playerdir+5,55,5); + CreateShotA1(bossX,bossY,5,playerdir,55,5); + CreateShotA1(bossX,bossY,5,playerdir-5,55,5); + CreateShotA1(bossX,bossY,5,playerdir-10,55,5); + newdir = playerdir-15; + wait(5); + + loop(40){ + CreateShotA1(bossX,bossY,5,newdir+10,55,5); + CreateShotA1(bossX,bossY,5,newdir+5,55,5); + CreateShotA1(bossX,bossY,5,newdir,55,5); + CreateShotA1(bossX,bossY,5,newdir-5,55,5); + CreateShotA1(bossX,bossY,5,newdir-10,55,5); + newdir = newdir-15; + wait(5); + } +} + +task renderBoss { + // Declare local variables, used for this task only + let dir; + let speed; + + // Moved from @Initialize + + // Giving the bossObj a "texture" + ObjPrim_SetTexture(bossObj, imgBoss); + // Which part to render -> remember to base this on the sprite itself + ObjSprite2D_SetSourceRect(bossObj,0,0,128,128); + // Moving our boss around from "true centre" + ObjSprite2D_SetDestCenter(bossObj); + // Scaling the boss sprite + ObjRender_SetScaleXYZ(bossObj,1.2,1.2,0); + // While the boss is not defeated yet + + while (!Obj_IsDeleted(bossObj)){ // "!" mark means "OPPOSITE of whatever comes next, meaning overall : While boss is NOT DELETED" + + // Update boss speed/direction + dir = ObjMove_GetAngle(bossObj); + speed = ObjMove_GetSpeed(bossObj); + + // Actual code for animation handling + + // Idle animation + if(speed == 0){ + ObjRender_SetAngleXYZ(bossObj,0,0,0); + + // if (aniframe....) -> IF the aniframe is this value, SHOW this sprite image + if (aniframe < 15){ObjSprite2D_SetSourceRect(bossObj,0,0,128,128);} + if (aniframe >= 15 && aniframe < 30){ObjSprite2D_SetSourceRect(bossObj,0,128,128,256);} + if (aniframe >= 30 && aniframe < 45){ObjSprite2D_SetSourceRect(bossObj,0,256,128,384);} + if (aniframe >= 45){ObjSprite2D_SetSourceRect(bossObj,128,128,256,256);} + } + // Left/Right animation + else if (cos(dir)<0){ + + aniframe2=0; + aniframe2+=2; + if(aniframe2 > 60){aniframe2 = 15;} + + ObjRender_SetAngleXYZ(bossObj,0,0,0); + if (aniframe2 < 15){ObjSprite2D_SetSourceRect(bossObj,256,0,384,128);} + if (aniframe2 >= 15){ObjSprite2D_SetSourceRect(bossObj,256,128,384,256);} + } + + else if (cos(dir)>0){ + + aniframe2=0; + aniframe2+=2; + if(aniframe2 > 60){aniframe2 = 15;} + + ObjRender_SetAngleXYZ(bossObj,0,0,0); + if (aniframe2 < 15){ObjSprite2D_SetSourceRect(bossObj,256,256,384,384);} + if (aniframe2 >= 15){ObjSprite2D_SetSourceRect(bossObj,256,384,384,512);} + } + + //Counting aniframe - ++ = up 1 per frame + aniframe+=2; + //Resetting aniframe if over predefined value + if(aniframe > 60){aniframe = 0;} + + // These two code lines above will ensure the idle loop. + + yield; + } +} + +task BossMove{ + + wait(60); + fire; + wait(250); + + loop{ + while(ObjEnemy_GetInfo(bossObj,INFO_LIFE)<=0){return;} + ObjMove_SetDestAtSpeed(bossObj,rand(10,280),bossY,3); + wait(30); + fire; + wait(250); + yield; + } + +} + +task ending{ + // While the boss is still alive, keep yielding (script works normally) + + while(ObjEnemy_GetInfo(bossObj,INFO_LIFE)>0){ + yield; + } + + DeleteShotAll(TYPE_ALL,TYPE_ITEM); + PlaySE(bossdefeatSFX); + TExplosionA(bossX,bossY,10,0.5); + wait(120); + PlaySE(bossdefeatSFX); + Obj_Delete(bossObj); + TExplosionA(bossX,bossY,10,0.5); + wait(120); + CloseScript(GetOwnScriptID); +} + +// I SPENT TWO DAYS TO FIGURE THIS OUT LMAO + +task shotyeet{ + while(ObjEnemy_GetInfo(bossObj,INFO_LIFE)>0){ + yield; + } + + loop{ + DeleteShotAll(TYPE_ALL,TYPE_ITEM); + yield; + } + +} \ No newline at end of file diff --git a/script/3drender/sounds/bossdie.wav b/script/3drender/sounds/bossdie.wav new file mode 100644 index 0000000..3020f3e Binary files /dev/null and b/script/3drender/sounds/bossdie.wav differ diff --git a/script/3drender/sounds/cardget.wav b/script/3drender/sounds/cardget.wav new file mode 100644 index 0000000..9f7a6c6 Binary files /dev/null and b/script/3drender/sounds/cardget.wav differ diff --git a/script/3drender/sounds/cardstart.wav b/script/3drender/sounds/cardstart.wav new file mode 100644 index 0000000..ab3dcb1 Binary files /dev/null and b/script/3drender/sounds/cardstart.wav differ diff --git a/script/3drender/sounds/hina.mp3 b/script/3drender/sounds/hina.mp3 new file mode 100644 index 0000000..8c6f424 Binary files /dev/null and b/script/3drender/sounds/hina.mp3 differ diff --git a/script/3drender/sprite/cardbg3.png b/script/3drender/sprite/cardbg3.png new file mode 100644 index 0000000..abe2443 Binary files /dev/null and b/script/3drender/sprite/cardbg3.png differ diff --git a/script/3drender/sprite/cardbg4.png b/script/3drender/sprite/cardbg4.png new file mode 100644 index 0000000..00da818 Binary files /dev/null and b/script/3drender/sprite/cardbg4.png differ diff --git a/script/3drender/sprite/cirno.png b/script/3drender/sprite/cirno.png new file mode 100644 index 0000000..5cdd601 Binary files /dev/null and b/script/3drender/sprite/cirno.png differ diff --git a/script/3drender/sprite/dafloor.png b/script/3drender/sprite/dafloor.png new file mode 100644 index 0000000..ab7c265 Binary files /dev/null and b/script/3drender/sprite/dafloor.png differ diff --git a/script/3drender/sprite/dafloorEX.png b/script/3drender/sprite/dafloorEX.png new file mode 100644 index 0000000..abe2443 Binary files /dev/null and b/script/3drender/sprite/dafloorEX.png differ diff --git a/script/3drender/sprite/damagicwall.png b/script/3drender/sprite/damagicwall.png new file mode 100644 index 0000000..2540816 Binary files /dev/null and b/script/3drender/sprite/damagicwall.png differ diff --git a/script/3drender/sprite/enm_yuyuko.png b/script/3drender/sprite/enm_yuyuko.png new file mode 100644 index 0000000..99edb57 Binary files /dev/null and b/script/3drender/sprite/enm_yuyuko.png differ diff --git a/script/3drender/sprite/iamp_yuyu.png b/script/3drender/sprite/iamp_yuyu.png new file mode 100644 index 0000000..b1c57a2 Binary files /dev/null and b/script/3drender/sprite/iamp_yuyu.png differ diff --git a/script/3drender/sprite/quicknote_yuyuko.txt b/script/3drender/sprite/quicknote_yuyuko.txt new file mode 100644 index 0000000..ae0198a --- /dev/null +++ b/script/3drender/sprite/quicknote_yuyuko.txt @@ -0,0 +1 @@ +128 x 128 = 1 sprite (yuyuko) \ No newline at end of file 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..400c08d 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/ExRumia/replay/ExRumia_Stage_replay01.dat b/script/ExRumia/replay/ExRumia_Stage_replay01.dat new file mode 100644 index 0000000..b68b194 Binary files /dev/null and b/script/ExRumia/replay/ExRumia_Stage_replay01.dat differ diff --git a/script/Gay_Package.dnh b/script/Gay_Package.dnh new file mode 100644 index 0000000..5987498 Binary files /dev/null and b/script/Gay_Package.dnh 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_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/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..72819bb --- /dev/null +++ b/script/KevinSystem/GeneralSoundLib.txt @@ -0,0 +1,113 @@ +// 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(); + +// 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, 35); + LoadEx(fire2, bullet2, 35); + 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(pausesfx, pause, 20); + LoadEx(choose, selection, 18); + LoadEx(thundersfx, thunder, 25); + LoadEx(charge, chargeA, 40); + LoadEx(phase, chargeB, 25); + LoadEx(fire3, bullet3, 35); + LoadEx(bombsfx, bomb, 50); + LoadEx(extendsfx, extend, 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", 45); +} + +// 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/KevinShot/KevinShot_Alt_HD.png b/script/KevinSystem/KevinShot/KevinShot_Alt_HD.png new file mode 100644 index 0000000..1dca553 Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_Alt_HD.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..a972d15 Binary files /dev/null and b/script/KevinSystem/KevinShot/KevinShot_Alt_HD_Fireball.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..0801a19 --- /dev/null +++ b/script/KevinSystem/KevinShot/shotconst_HD.txt @@ -0,0 +1,108 @@ + +local +{ + LoadTextureEx(GetCurrentScriptDirectory ~ "./KevinShot_Alt_HD.png", true, true); + LoadTextureEx(GetCurrentScriptDirectory ~ "./KevinShot_Alt_HD_Fireball.png", true, true); + LoadEnemyShotData(GetCurrentScriptDirectory ~ "shotdata_HD.txt"); + LoadEnemyShotData(GetCurrentScriptDirectory ~ "shotdata_HD_2.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_PEOPLE_RED = 2011; +const KEV_PEOPLE_ORANGE = 2012; +const KEV_PEOPLE_YELLOW = 2013; +const KEV_PEOPLE_GREEN = 2014; +const KEV_PEOPLE_AQUA = 2015; +const KEV_PEOPLE_LAVENDER = 2016; +const KEV_PEOPLE_PURPLE = 2017; +const KEV_PEOPLE_PINK = 2018; +const KEV_PEOPLE_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_AMULET_RED = 2033; +const KEV_AMULET_ORANGE = 2034; +const KEV_AMULET_YELLOW = 2035; +const KEV_AMULET_GREEN = 2036; +const KEV_AMULET_AQUA = 2037; +const KEV_AMULET_LAVENDER = 2038; +const KEV_AMULET_PURPLE = 2039; +const KEV_AMULET_PINK = 2040; +const KEV_AMULET_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; + + diff --git a/script/KevinSystem/KevinShot/shotdata_HD.txt b/script/KevinSystem/KevinShot/shotdata_HD.txt new file mode 100644 index 0000000..f849ce5 --- /dev/null +++ b/script/KevinSystem/KevinShot/shotdata_HD.txt @@ -0,0 +1,100 @@ +#UserShotData + +shot_image = "./KevinShot_Alt_HD.png" + +ShotData { id = 2000 rect = (0,0,128,128) collision = 26 delay_color = (255,255,255) } //RED +ShotData { id = 2001 rect = (128,0,256,128) collision = 26 delay_color = (255,255,255) } //ORANGE +ShotData { id = 2002 rect = (256,0,384,128) collision = 26 delay_color = (255,255,255) } //YELLOW +ShotData { id = 2003 rect = (384,0,512,128) collision = 26 delay_color = (255,255,255) } //GREEN +ShotData { id = 2004 rect = (512,0,640,128) collision = 26 delay_color = (255,255,255) } //AQUA +ShotData { id = 2005 rect = (640,0,768,128) collision = 26 delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2006 rect = (768,0,896,128) collision = 26 delay_color = (255,255,255) } //PURPLE +ShotData { id = 2007 rect = (896,0,1024,128) collision = 26 delay_color = (255,255,255) } //PINK +ShotData { id = 2008 rect = (1024,0,1152,128) collision = 26 delay_color = (255,255,255) } //WHITE + +ShotData { id = 2011 rect = (0,128,128,256) collision = (17,0,-7) delay_color = (255,255,255) } //RED +ShotData { id = 2012 rect = (128,128,256,256) collision = (17,0,-7) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2013 rect = (256,128,384,256) collision = (17,0,-7) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2014 rect = (384,128,512,256) collision = (17,0,-7) delay_color = (255,255,255) } //GREEN +ShotData { id = 2015 rect = (512,128,640,256) collision = (17,0,-7) delay_color = (255,255,255) } //AQUA +ShotData { id = 2016 rect = (640,128,768,256) collision = (17,0,-7) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2017 rect = (768,128,896,256) collision = (17,0,-7) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2018 rect = (896,128,1024,256) collision = (17,0,-7) delay_color = (255,255,255) } //PINK +ShotData { id = 2019 rect = (1024,128,1152,256) collision = (17,0,-7) delay_color = (255,255,255) } //WHITE + +ShotData { id = 2022 rect = (0,256,128,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //RED +ShotData { id = 2023 rect = (128,256,256,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2024 rect = (256,256,384,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2025 rect = (384,256,512,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //GREEN +ShotData { id = 2026 rect = (512,256,640,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //AQUA +ShotData { id = 2027 rect = (640,256,768,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2028 rect = (768,256,896,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2029 rect = (896,256,1024,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //PINK +ShotData { id = 2030 rect = (1024,256,1152,384) collision = (8,0,6) collision = (8,0,-6) delay_color = (255,255,255) } //WHITE + +ShotData { id = 2033 rect = (0,384,128,512) collision = (28,0,0) delay_color = (255,255,255) } //RED +ShotData { id = 2034 rect = (128,384,256,512) collision = (28,0,0) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2035 rect = (256,384,384,512) collision = (28,0,0) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2036 rect = (384,384,512,512) collision = (28,0,0) delay_color = (255,255,255) } //GREEN +ShotData { id = 2037 rect = (512,384,640,512) collision = (28,0,0) delay_color = (255,255,255) } //AQUA +ShotData { id = 2038 rect = (640,384,768,512) collision = (28,0,0) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2039 rect = (768,384,896,512) collision = (28,0,0) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2040 rect = (896,384,1024,512) collision = (28,0,0) delay_color = (255,255,255) } //PINK +ShotData { id = 2041 rect = (1024,384,1152,512) collision = (28,0,0) delay_color = (255,255,255) } //WHITE + +ShotData { id = 2044 rect = (0,512,128,640) collision = (8,0,20) delay_color = (255,255,255) } //RED +ShotData { id = 2045 rect = (128,512,256,640) collision = (8,0,20) delay_color = (255,255,255) } //ORANGE +ShotData { id = 2046 rect = (256,512,384,640) collision = (8,0,20) delay_color = (255,255,255) } //YELLOW +ShotData { id = 2047 rect = (384,512,512,640) collision = (8,0,20) delay_color = (255,255,255) } //GREEN +ShotData { id = 2048 rect = (512,512,640,640) collision = (8,0,20) delay_color = (255,255,255) } //AQUA +ShotData { id = 2049 rect = (640,512,768,640) collision = (8,0,20) delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2050 rect = (768,512,896,640) collision = (8,0,20) delay_color = (255,255,255) } //PURPLE +ShotData { id = 2051 rect = (896,512,1024,640) collision = (8,0,20) delay_color = (255,255,255) } //PINK +ShotData { id = 2052 rect = (1024,512,1152,640) collision = (8,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..aa52f63 --- /dev/null +++ b/script/KevinSystem/KevinShot/shotdata_HD_2.txt @@ -0,0 +1,13 @@ +#UserShotData + +shot_image = "./KevinShot_Alt_HD_Fireball.png" + +ShotData { id = 2075 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 = ADD_ARGB collision = 13 delay_color = (255,255,255) } //RED +ShotData { id = 2076 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 = ADD_ARGB collision = 13 delay_color = (255,255,255) } //ORANGE +ShotData { id = 2077 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 = ADD_ARGB collision = 13 delay_color = (255,255,255) } //YELLOW +ShotData { id = 2078 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 = ADD_ARGB collision = 13 delay_color = (255,255,255) } //GREEN +ShotData { id = 2079 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 = ADD_ARGB collision = 13 delay_color = (255,255,255) } //AQUA +ShotData { id = 2080 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 = ADD_ARGB collision = 13 delay_color = (255,255,255) } //LAVENDER +ShotData { id = 2081 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 = ADD_ARGB collision = 13 delay_color = (255,255,255) } //PURPLE +ShotData { id = 2082 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 = ADD_ARGB collision = 13 delay_color = (255,255,255) } //PINK +ShotData { id = 2083 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 = ADD_ARGB 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..735ce60 --- /dev/null +++ b/script/KevinSystem/Kevin_PlayerLib.txt @@ -0,0 +1,345 @@ +/* -------------------------------------------------------------------- + + 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" + +float universalAlpha = GetAreaCommonData("Config", "PlayerShotOpacity", 60); + +task _DeleteEffect(obj){ + ObjRender_SetBlendType(obj, BLEND_ADD_ARGB); + Obj_SetRenderPriorityI(obj, 41); + ascent(i in 0..30){ + ObjRender_SetAlpha(obj, Interpolate_Decelerate(100*(universalAlpha/100), 0, i/30)); + ObjRender_SetScaleXYZ(obj, Interpolate_Decelerate(0.5, 1.5, i/30)); + 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)-1); + + alternative(death) + case(true){ + ascent(i in 0..time){ + float scaliealpha = Interpolate_Decelerate(255, 0, i/time); + float scaliesize = Interpolate_Decelerate(0.1, 1.5, 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(1.5, 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(aura); + ObjRender_SetAngleZ(aura, curang+1); + 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, 225); + 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; +} + +/* +------------------------------------------------------ + + 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. The last three parameters control the drop rate, and are significantly higher for Erika & Tenshi. + +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){ + + NotifyEventAll(EV_PIV_250, [ObjMove_GetX(target), ObjMove_GetY(target)]); + wait(maxrate + addrate*floor(dist/adddist)); + + } + else{yield;} + } + +} + +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; +} + +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; + +} \ 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..791442f --- /dev/null +++ b/script/KevinSystem/Kevin_System.txt @@ -0,0 +1,862 @@ + +// 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); + +/* +Lifebar empty = (5, 5, 534, 34) +Lifebar split = (6, 38, 18, 74) +Lifebar full = (5, 78, 16, 108) + +*/ + +// + +//#include "./../script/soundtask.txt" + +#include "script/KevinSystem/GeneralSoundLib.txt" + +@Initialize +{ + _SoundTask(); + + SetStgFrame(504, 0, 1415, 997, 20, 80); + + sel = prand_int(0, 99); + + SetPauseScriptPath(GetCurrentScriptDirectory() ~ "kevin_system/Kevin_Pause.txt"); + SetEndSceneScriptPath(GetCurrentScriptDirectory() ~ "kevin_system/Kevin_EndScene.txt"); + SetReplaySaveSceneScriptPath(GetCurrentScriptDirectory() ~ "kevin_system/Kevin_ReplaySave.txt"); + + InitFrame(); + + //TInstallFont(); Moved to package. + + TScore(); + //TGraze(); + //SetPlayerLife(9); + + LifeDisplay(); + 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); + } +} + +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( + 250, 960, 24, + "", "Exotc350 DmBd BT", + 0xA70053, 0xA70053, + 0xFFFFFF, 2, + 21 + ); + + ObjText_SetFontBold(ExtendThresholdText, true); + ObjText_SetHorizontalAlignment(ExtendThresholdText, ALIGNMENT_RIGHT); + + int count = 0; + // Millions + let req = [ + + ]; + + if(GetCommonData("Difficulty", "Arcade") == "Arcade"){req = [20, 80, 200, 500, 800, 1200, 2500, 5000];} + else{req = [15, 50, 100, 180, 300, 600, 1000, 2000, 4000];} + + let next = 0; + + loop{ + count = (trunc(GetScore())/10)*10; + if(next <= length(req)-1){ + if(count >= req[next]*1000000){ + next++; + SetPlayerLife(GetPlayerLife+1); + ExtendSFX; + ExtendEffect; + } + } + if(next != 8){ObjText_SetText(ExtendThresholdText, "NEXT: " ~ DigitToCommaArray(req[next]*1000000));} + else{ObjText_SetText(ExtendThresholdText, "MAX EXTEND");} + 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); + +} + +//---------------------------------------------------- +//枠外の背景表示 +//---------------------------------------------------- +function InitFrame() +{ + let path = GetCurrentScriptDirectory() ~ "img/ThiccHUD.png"; + //if(false){path = GetCurrentScriptDirectory() ~ "img/literallywhat.png";} + //else{path = GetCurrentScriptDirectory() ~ "img/altHUD.png";} + let obj = ObjPrim_Create(OBJ_SPRITE_2D); + LoadTextureEx(path, true, true); + ObjPrim_SetTexture(obj, path); + //ObjRender_SetScaleXYZ(obj, 0.5, 0.5, 1); + ObjRender_SetTextureFilterMag(obj, FILTER_NONE); + ObjRender_SetTextureFilterMin(obj, FILTER_NONE); + ObjRender_SetTextureFilterMip(obj, FILTER_NONE); + Obj_SetRenderPriority(obj, 0); + ObjSprite2D_SetSourceRect(obj, 0, 0, GetScreenWidth(), GetScreenHeight()); + ObjSprite2D_SetDestRect(obj, 0, 0, GetScreenWidth(), GetScreenHeight()); + + int diffText = CreateTextObject( + offsetX+150, baseY*0.3, 60, + "", "Exotc350 DmBd BT", + 0xFFFFFF, 0xFFFFFF, + 0xFFFFFF, 3, + 1 + ); + + ObjText_SetFontBold(diffText, true); + ObjText_SetHorizontalAlignment(diffText, ALIGNMENT_CENTER); + + /* + if(GetCommonData("Difficulty", "Arcade") == "Arcade"){ + ObjText_SetText(diffText, "Arcade Mode"); + ObjText_SetFontColorTop(diffText, 0x8100CE); + ObjText_SetFontColorBottom(diffText,0xAC7DFF); + ObjText_SetFontBorderType(diffText, BORDER_FULL); + ObjText_SetFontBorderColor(diffText, 0xFFFFFF); + } + + else{ + ObjText_SetText(diffText, "Gentle Mode"); + ObjText_SetFontColorTop(diffText, 0xFF993F); + ObjText_SetFontColorBottom(diffText,0xFFCFA6); + ObjText_SetFontBorderType(diffText, BORDER_FULL); + ObjText_SetFontBorderColor(diffText, 0xFFFFFF); + } + */ +} + +//---------------------------------------------------- +//スコア表示 +//---------------------------------------------------- + +task THighScore(){ + + let objScoreNo = ObjText_Create(); + ObjText_SetFontSize(objScoreNo, 58); + ObjText_SetFontBold(objScoreNo, true); + ObjText_SetFontType(objScoreNo, "Anke Calligraph"); + ObjText_SetFontColorTop(objScoreNo, 0xFFA157); + ObjText_SetFontColorBottom(objScoreNo,0xFFC232); + ObjText_SetFontBorderType(objScoreNo, BORDER_FULL); + ObjText_SetFontBorderColor(objScoreNo, 0xFFFFFF); + ObjText_SetFontBorderWidth(objScoreNo, 3); + //ObjText_SetFontWeight(objScoreNo, 1000); + Obj_SetRenderPriorityI(objScoreNo, 1); + ObjRender_SetX(objScoreNo, offsetX-10); // Subject to change + ObjRender_SetY(objScoreNo, baseY*0.8); // Same as above + + while(true){ + let score = GetAreaCommonData("hiscoredata", "hiscore", 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 objScore = ObjText_Create(); + ObjText_SetFontSize(objScore, 24); + ObjText_SetFontBold(objScore, true); + ObjText_SetFontType(objScore, "Exotc350 DmBd BT"); + ObjText_SetFontColorTop(objScore,0xFFFFFF); + ObjText_SetFontColorBottom(objScore,0xFFFFFF); + ObjText_SetFontBorderType(objScore, BORDER_FULL); + ObjText_SetFontBorderColor(objScore, 0x25379D); + ObjText_SetFontBorderWidth(objScore, 3); + ObjText_SetText(objScore, "SCORE"); + //ObjText_SetFontWeight(objScore, 1000); + Obj_SetRenderPriorityI(objScore, 79); + ObjRender_SetX(objScore, 12); // Subject to change + ObjRender_SetY(objScore, 48); // Same as above + Obj_SetVisible(objScore, false); + + let objScoreNo = ObjText_Create(); + ObjText_SetFontSize(objScoreNo, 40); + ObjText_SetFontBold(objScoreNo, true); + ObjText_SetFontType(objScoreNo, "Origami Mommy"); + ObjText_SetFontColorTop(objScoreNo,0xFFFFFF); + ObjText_SetFontColorBottom(objScoreNo,0xFFFFFF); + ObjText_SetFontBorderType(objScoreNo, BORDER_FULL); + ObjText_SetFontBorderColor(objScoreNo, 0x25379D); + ObjText_SetFontBorderWidth(objScoreNo, 4); + //ObjText_SetFontWeight(objScoreNo, 1000); + Obj_SetRenderPriorityI(objScoreNo, 79); + ObjText_SetSidePitch(objScoreNo, -3); + ObjRender_SetX(objScoreNo, 10); // Subject to change + ObjRender_SetY(objScoreNo, 10); // Same as above + + while(true){ + let score = trunc(GetScore()/10) * 10; + score = min(score,999999999990); + let yass = DigitToCommaArray(score); + ObjText_SetText(objScoreNo, yass); + + if(ObjMove_GetY(GetPlayerObjectID()) < GetStgFrameHeight()/6){ + ObjRender_SetAlpha(objScore, 60); + ObjRender_SetAlpha(objScoreNo, 60); + } + else{ + ObjRender_SetAlpha(objScore, 255); + ObjRender_SetAlpha(objScoreNo, 255); + } + + 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 objPIV = ObjText_Create(); + ObjText_SetFontSize(objPIV, 21); + ObjText_SetFontBold(objPIV, true); + ObjText_SetFontType(objPIV, "Exotc350 DmBd BT"); + ObjText_SetFontColorTop(objPIV,0xFFFFFF); + ObjText_SetFontColorBottom(objPIV,0xFFFFFF); + ObjText_SetFontBorderType(objPIV, BORDER_FULL); + ObjText_SetFontBorderColor(objPIV, 0xDC47C8); + ObjText_SetFontBorderWidth(objPIV, 3); + ObjText_SetText(objPIV, "MULTIPLIER"); + ObjText_SetHorizontalAlignment(objPIV, ALIGNMENT_RIGHT); + //ObjText_SetFontWeight(objPIV, 1000); + Obj_SetRenderPriorityI(objPIV, 79); + ObjRender_SetX(objPIV, GetStgFrameWidth()-15); // Subject to change + ObjRender_SetY(objPIV, 44); // Same as above + + let objPIVNum = ObjText_Create(); + ObjText_SetFontSize(objPIVNum, 30); + 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_RIGHT); + //ObjText_SetFontWeight(objPIVNum, 1000); + Obj_SetRenderPriorityI(objPIVNum, 79); + ObjRender_SetX(objPIVNum, GetStgFrameWidth()-12); // Subject to change + ObjRender_SetY(objPIVNum, 10); // Same as above + // DEBUG + //Obj_SetVisible(objPIV, false); + + while(true){ + let value = GetAreaCommonData("PIV", "currentvalue", 0); + value = min(value,9999999990); + //PIVMultiplierValue = value/1000; + let yass = vtos("5.2f", value/10000); + ObjText_SetText(objPIVNum, yass ~ "x"); + + if(ObjMove_GetY(GetPlayerObjectID()) < GetStgFrameHeight()/6){ + ObjRender_SetAlpha(objPIV, 60); + ObjRender_SetAlpha(objPIVNum, 60); + } + else{ + ObjRender_SetAlpha(objPIV, 255); + ObjRender_SetAlpha(objPIVNum, 255); + } + 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, 1); + ObjPrim_SetTexture(lifecounter, lifeshow); + //ObjSpriteList2D_SetSourceRect(lifecounter, 256, 0, 384, 128); + //ObjRender_SetScaleXYZ(lifecounter, 0.5, 0.5, 1); + //ObjSpriteList2D_SetDestCenter(lifecounter); + + loop{ + ObjSpriteList2D_ClearVertexCount(lifecounter); + ObjSpriteList2D_SetSourceRect(lifecounter, 256, 0, 384, 128); + ObjSpriteList2D_SetDestCenter(lifecounter); + ObjRender_SetScaleXYZ(lifecounter, 0.26*scale, 0.26*scale, 1); + liferemain = GetPlayerLife(); + ascent(i in 0..liferemain){ + ObjRender_SetPosition(lifecounter, 550-10+i*25, 1040, 0); + ObjSpriteList2D_AddVertex(lifecounter); + } + yield; + } + +} +// New spell task +task SpellDisplay{ + + let spellremain; + let spellcounter = ObjPrim_Create(OBJ_SPRITE_LIST_2D); + let spellshow = graphicimg; + Obj_SetRenderPriorityI(spellcounter, 1); + ObjPrim_SetTexture(spellcounter, spellshow); + + loop{ + ObjSpriteList2D_ClearVertexCount(spellcounter); + ObjSpriteList2D_SetSourceRect(spellcounter, 384, 0, 512, 128); + ObjSpriteList2D_SetDestCenter(spellcounter); + ObjRender_SetScaleXYZ(spellcounter, 0.26*scale, 0.26*scale, 1); + spellremain = GetPlayerSpell(); + ascent(i in 0..spellremain){ + ObjRender_SetPosition(spellcounter, 1000+10+i*25, 1040, 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, 90, 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, 70, 12 + (890-2) * lifeRate, 110); + 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()) * (1-rate); + ObjSpriteList2D_SetDestRect(objDivision, x-3, 65, x+24, 115); + ObjSpriteList2D_AddVertex(objDivision); + } + + //Boss star rendering + ObjRender_SetScaleXYZ(objStar, 0.5, 0.5, 1); + ObjSpriteList2D_SetSourceRect(objStar, 0, 169, 268, 430); + Obj_SetRenderPriority(objStar, 1); + ascent(iStep in 0 .. countRemStep) + { + ObjRender_SetPosition(objStar, GetStgFrameWidth()*1.36-iStep*32, 30, 1); + ObjSpriteList2D_SetDestCenter(objStar); + ObjSpriteList2D_AddVertex(objStar); + } + + lifeRateRender += 0.01; + lifeRateRender = min(lifeRateRender, 1); + lastRemStep = countRemStep; + + if(ObjMove_GetY(GetPlayerObjectID()) < GetStgFrameHeight()/6){ + ObjRender_SetAlpha(obj, 60); + ObjRender_SetAlpha(obj, 30); + } + else{ + ObjRender_SetAlpha(obj, 255); + ObjRender_SetAlpha(objLifebar, 140); + } + } +} + +//---------------------------------------------------- +//タイマー表示 +//---------------------------------------------------- +task TBossTimer +{ + let textTimer = ObjText_Create(); + ObjText_SetFontSize(textTimer, 35); + ObjText_SetFontType(textTimer, "Connecting Chain Handserif"); + + //ObjText_SetMaxWidth(textTimer, GetStgFrameWidth()/6); + ObjText_SetHorizontalAlignment(textTimer, ALIGNMENT_CENTER); + + ObjText_SetFontBold(textTimer, true); + ObjText_SetFontColorTop(textTimer, 0xFFFFFF); + ObjText_SetFontColorBottom(textTimer, 0xFFFFFF); + ObjText_SetFontBorderType(textTimer, BORDER_FULL); + ObjText_SetFontBorderColor(textTimer, 0xA639F0); + ObjText_SetFontBorderWidth(textTimer, 3.4); + Obj_SetRenderPriorityI(textTimer, 73); + ObjRender_SetX(textTimer, GetStgFrameWidth()/8-10); + ObjRender_SetY(textTimer, 110); + 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, 99.99); + ObjText_SetText(textTimer, "TIME: " ~ rtos("00.00", timer)); + ObjSpriteList2D_SetSourceRect(obj, 404, 225, 537, 374); + ObjRender_SetScaleXYZ(obj, 0.38, 0.38, 1); + ObjSpriteList2D_SetDestCenter(obj); + ObjRender_SetPosition(obj, 4*GetStgFrameWidth()/5+62, GetStgFrameHeight()/8-25, 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){_Timeout();} + ObjText_SetFontBorderColor(textTimer, 0xF0396C); + } + else{} + if(ObjMove_GetY(GetPlayerObjectID()) < GetStgFrameHeight()/6){ + 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(80, 45, 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() +{ + let objText = ObjText_Create(); + ObjText_SetFontSize(objText, 48); + ObjText_SetFontBold(objText, true); + ObjText_SetFontType(objText, "Anke Calligraph"); + ObjText_SetFontColorTop(objText, 0x6747FF); + ObjText_SetFontColorBottom(objText, 0xAEC4FF); + ObjText_SetFontBorderType(objText, BORDER_FULL); + ObjText_SetFontBorderColor(objText, 255, 255, 255); + 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, 12); + ObjText_SetFontBold(objText, true); + ObjText_SetFontColorTop(objText, 128, 128, 255); + ObjText_SetFontColorBottom(objText, 64, 64, 255); + ObjText_SetFontBorderType(objText, BORDER_FULL); + ObjText_SetFontBorderColor(objText,255, 255, 255); + ObjText_SetFontBorderWidth(objText, 1); + Obj_SetRenderPriority(objText, 1.0); + + let px = GetStgFrameLeft() + GetStgFrameWidth() - 18; + let py = GetStgFrameTop() + GetScreenHeight() - 14; + ObjRender_SetX(objText, px); + ObjRender_SetY(objText, py); + + loop + { + let fps = GetReplayFps(); + let text = vtos("02d", fps); + ObjText_SetText(objText, text); + 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/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_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_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_arabqueenhousama.wav b/script/KevinSystem/PlayerSFX/bfxr_arabqueenhousama.wav new file mode 100644 index 0000000..d24862e Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_arabqueenhousama.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_basefire.wav b/script/KevinSystem/PlayerSFX/bfxr_basefire.wav new file mode 100644 index 0000000..dff783c Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_basefire.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_fire.wav b/script/KevinSystem/PlayerSFX/bfxr_fire.wav new file mode 100644 index 0000000..6c241e4 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_fire.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_kyliejennerarabqueen.wav b/script/KevinSystem/PlayerSFX/bfxr_kyliejennerarabqueen.wav new file mode 100644 index 0000000..327dbb5 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_kyliejennerarabqueen.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_scythecall.wav b/script/KevinSystem/PlayerSFX/bfxr_scythecall.wav new file mode 100644 index 0000000..99b3040 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_scythecall.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/bfxr_teleporthigh.wav b/script/KevinSystem/PlayerSFX/bfxr_teleporthigh.wav new file mode 100644 index 0000000..a493cf0 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_teleporthigh.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_teleportlow.wav b/script/KevinSystem/PlayerSFX/bfxr_teleportlow.wav new file mode 100644 index 0000000..2e8b8b2 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_teleportlow.wav differ diff --git a/script/KevinSystem/PlayerSFX/bfxr_watershoot.wav b/script/KevinSystem/PlayerSFX/bfxr_watershoot.wav new file mode 100644 index 0000000..6cfced3 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/bfxr_watershoot.wav differ diff --git a/script/KevinSystem/PlayerSFX/birdcall05.wav b/script/KevinSystem/PlayerSFX/birdcall05.wav new file mode 100644 index 0000000..ec6c7b9 Binary files /dev/null and b/script/KevinSystem/PlayerSFX/birdcall05.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/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..357502c --- /dev/null +++ b/script/KevinSystem/PlayerSoundLib.dnh @@ -0,0 +1,64 @@ +// Sound effects for player scripts go here. + +// Link to sound folder + +let sddir = GetCurrentScriptDirectory() ~ "./PlayerSFX"; +//let sddir = GetCurrentScriptDirectory() ~ "./sound"; + +let SFXVol = GetAreaCommonData("Config", "SEVol", 100) * 0.01; + +// Function for loading and setting volume of a sound object +function LoadEx(targetobj, targetpath, targetvol){ + + ObjSound_Load(targetobj, targetpath); + ObjSound_SetVolumeRate(targetobj, targetvol * SFXVol); + ObjSound_SetSoundDivision(targetobj, SOUND_SE); + +} + +// Universal sounds +let baseshot = sddir ~ "./bfxr_Base.wav"; +let bomb = sddir ~ "./bfxr_kyliejennerarabqueen.wav"; +let ded = sddir ~ "./bfxr_PlayerShootdown.wav"; +let hit = sddir ~ "./bfxr_PlayerHit.wav"; +let graze = sddir ~ "./bfxr_Graze.wav"; + +let basesfx = ObjSound_Create(); +let bombsfx = ObjSound_Create(); +let deathsfx = ObjSound_Create(); +let predeathsfx = ObjSound_Create(); +let grazesfx = ObjSound_Create(); +/**/ +// Marisa & Housui's sounds, "inferno" is shared with Eri/Ten + +let teleporthigh = sddir ~ "./bfxr_teleporthigh.wav"; +let teleportlow = sddir ~ "./bfxr_teleportlow.wav"; +let missileboom = ObjSound_Create(); +let inferno = ObjSound_Create(); +let bombhousui = ObjSound_Create(); + +// Pankevin & Kouda's sounds + +let orbfront = ObjSound_Create(); +let orbback = ObjSound_Create(); +let scythecall = ObjSound_Create(); +let splash = ObjSound_Create(); +let scythefire = ObjSound_Create(); + +task _SoundTask(){ + LoadEx(basesfx, baseshot, 20); + LoadEx(bombsfx, bomb, 75); + LoadEx(deathsfx, ded, 40); + LoadEx(predeathsfx, hit, 100); + + LoadEx(orbfront, teleporthigh, 20); + LoadEx(orbback, teleportlow, 20); + LoadEx(scythecall, sddir ~ "./bfxr_scythecall.wav", 15); + LoadEx(splash, sddir ~ "./bfxr_splash.wav", 12.5); + LoadEx(scythefire, sddir ~ "./bfxr_watershoot.wav", 8); + + LoadEx(missileboom, sddir ~ "./bfxr_missileexplode.wav", 18); + LoadEx(inferno, sddir ~ "./bfxr_fire.wav", 20); + LoadEx(bombhousui, sddir ~ "./bfxr_arabqueenhousama.wav", 35); + LoadEx(grazesfx, graze, 40); +} 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..df2bfa3 Binary files /dev/null and b/script/KevinSystem/RyannSFX/ItemSFX/bfxr_GetItemSpecial.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/Universal_EnemyLib.dnh b/script/KevinSystem/Universal_EnemyLib.dnh new file mode 100644 index 0000000..7134e5e --- /dev/null +++ b/script/KevinSystem/Universal_EnemyLib.dnh @@ -0,0 +1,905 @@ +/* + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// + + UNIVERSAL LIBRARY FOR ENEMY-RELATED FUNCTIONS + +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// + +*/ + +// Code by Kevinmonitor with some assistance. +/* + +///////////// ENEMY SPAWNING DURING STAGES ///////////// + +*/ + +task _InitDifficulty(int diffInt){ + + if(GetCommonData("Difficulty", "Normal") == "Normal"){ + diffInt = 0; + } + + else if(GetCommonData("Difficulty", "Normal") == "Hyper"){ + diffInt = 1; + } + + else if(GetCommonData("Difficulty", "Normal") == "Unparalleled"){ + diffInt = 2; + } + + return; +} + +// Explosion Sound Effects + +task _RenderBoss(int enemy){ + + int aniidle = 0; + + string tex = "script/game/StageLib/BossAsset.png"; + + LoadTextureEx(tex, true, true); + + ObjPrim_SetTexture(enemy, tex); + ObjSprite2D_SetSourceRect(enemy, 0, 0, 512, 512); + ObjSprite2D_SetDestCenter(enemy); + ObjRender_SetScaleXYZ(enemy, 0.48); + + int nameText = CreateTextObject( + GetStgFrameWidth()*0.38, 10, 42, + "BOSS: Chimata Tenkyuu", "Connecting Chain Handserif", + 0x8ABFFF, 0xFFFFFF, + 0x552A9C, 3, + 1 + ); + + 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; + } + + } + +int itemScript = LoadScriptInThread("script/KevinSystem/kevin_system/KevinSystem_Item.txt"); +StartScript(itemScript); + +// 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; + + } + +// Hitbox and deletion + +task _HandleEnemyWellbeing(int enemyID, float sizeHitbox, float sizeHurtbox){ + + 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; + +} + +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; + +} + +// 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; + } +} + +// 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]); + + } + +// 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, + 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); + dmgCheck = ObjEnemy_GetInfo(Bitch, INFO_DAMAGE_PREVIOUS_FRAME); + timer++; + yield; + } + + if( + (-96 < enmX && enmX < STG_WIDTH+96) + && + (-96 < enmY && enmY < STG_HEIGHT+96) + ) + + { + _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(itemScript, EV_DROP_POINT_ENEMY, [enmX, enmY], timer, maxTimer, minPoint, maxPoint); + NotifyEvent(itemScript, EV_DROP_PIV_ENEMY, GetPlayerObjectID(), [enmX, enmY], minPIV, maxPIV, maxDist); + } + +} + +// 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; + + TExplosionA(enmX, enmY, 255/effectLength, 9/effectLength); + + /*ascent(i in 0..effectNum){ + _CreatePetal(rand(5, 10)*dir, rand(5, 10)*dir, rand(0, 360)); + dir *= -1; + //_CreatePetal(rand(50, 80), rand(-80, -50), rand(0, 360)); + }*/ + + _CreatePetal(rand(8, 11), rand(-8, -11), rand(0, 360)); + _CreatePetal(rand(-11, -8), rand(-2, 2), rand(0, 360)); + _CreatePetal(rand(8, 8), rand(-2, 2), rand(0, 360)); + _CreatePetal(rand(-11, -8), rand(8, 11), rand(0, 360)); + _CreatePetal(rand(8, 11), rand(8, 11), rand(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 = rand(-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/Universal_Lib.txt b/script/KevinSystem/Universal_Lib.txt new file mode 100644 index 0000000..ff799b9 --- /dev/null +++ b/script/KevinSystem/Universal_Lib.txt @@ -0,0 +1,339 @@ +/* -------------------------------------------------------------------- + + /////////////// UNIVERSAL/GENERAL LIBRARY ///////////////// + + A library meant for universal functions and including other libraries. + + -------------------------------------------------------------------- +*/ + +#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 + +const STG_WIDTH = GetStgFrameWidth(); +const STG_HEIGHT = GetStgFrameHeight(); + +InstallFont("script/KevinSystem/font/Connecting Chain Handserif.ttf"); +InstallFont("script/KevinSystem/font/AnkeCall.ttf"); + +// Placeholder + +let invalid = "script/KevinSystem/img/lol.png"; +let testEnemyTex = "script/game/StageLib/TestEnemy.png"; + +LoadTextureEx(invalid, true, true); +LoadTextureEx(testEnemyTex, true, true); + +int PetalEffect = ObjParticleList_Create(OBJ_PARTICLE_LIST_2D); + +_EffectListPreRender(PetalEffect, testEnemyTex, [512, 0, 768, 256]); +_SoundTask; + +// 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; +} + +// 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_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_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_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_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, 39); + 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/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/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/ThiccHUD.png b/script/KevinSystem/img/ThiccHUD.png new file mode 100644 index 0000000..7130de7 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/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..0e9864e 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..d554aa5 --- /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", 80); + LoadEx(LifeSFX, itemlib ~ "bfxr_LifeExtend.wav", 80); + LoadEx(CancelSFX, itemlib ~ "bfxr_GetItemCancel.wav", 20); + LoadEx(RegularItemSFX, itemlib ~ "bfxr_GetItem1.wav", 40); + LoadEx(SpecialItemSFX, itemlib ~ "bfxr_GetItemSpecial.wav", 40); +} + +// 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..509a212 --- /dev/null +++ b/script/KevinSystem/kevin_system/KevinSystem_Item.txt @@ -0,0 +1,276 @@ +// Item script + +#include "./Kevin_ItemConst.txt" +#include "./Kevin_ItemLib.txt" +#include "./ItemSoundLib.txt" +//#include "./Kevin_ItemData.txt; + +float PIV = 0; + +@Initialize{ + SetAutoDeleteObject(true); + _ItemSoundTask(); + SetDefaultBonusItemEnable(false); + LoadItemData(GetCurrentScriptDirectory ~ "./Kevin_ItemData.txt"); +} + +@MainLoop{ + PIV = GetAreaCommonData("PIV", "currentvalue", 0); + yield; +} + +@Event +{ + alternative (GetEventType()) + case (EV_GET_ITEM){ + + let obj = GetEventArgument(0); + + alternative(obj) + + case(POINT_REGULAR) { AddScore(GetAreaCommonData("PIV", "currentvalue", 0)); ObjSound_Play(CancelSFX);} + case(POINT_BHESTIE) { AddScore(2*GetAreaCommonData("PIV", "currentvalue", 0)); ObjSound_Play(SpecialItemSFX);} + case(POINT_RAINBOW) { AddScore(2*GetAreaCommonData("PIV", "currentvalue", 0)); ObjSound_Play(SpecialItemSFX);} + case(POINT_CANCEL) { AddScore(0.05*GetAreaCommonData("PIV", "currentvalue", 0)); ObjSound_Play(CancelSFX);} + + case(EXTEND_LIFE) { AddScore(PIV); SetPlayerLife(GetPlayerLife()+1); ObjSound_Play(SpellSFX);} + case(EXTEND_SPELL) { AddScore(PIV); SetPlayerSpell(GetPlayerSpell()+1); ObjSound_Play(SpecialItemSFX);} + + case(PIV_100) { SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue", 0)+100);} //ObjSound_Play(CancelSFX);} + case(PIV_250) { SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue", 0)+250);} //ObjSound_Play(CancelSFX);} + case(PIV_500) { SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue", 0)+500);} //ObjSound_Play(CancelSFX);} + + } + + case (EV_DELETE_SHOT_TO_ITEM){ + + float[] position = GetEventArgument(1); + CreateCancelItem(position[0], position[1]); + + } + + case (EV_CANCEL_ITEM) { + + let obj = GetEventArgument(0); + let type = GetEventArgument(1); + + _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)); + + } + + // 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, int killTimer, int maxTimer, int pointMin, int pointMax){ + + // If the player kills enemy within maxTimer, the enemy drops the maximum amount of point items + + int pointFinal = Interpolate_Smooth(pointMin, pointMax, min(1, maxTimer/killTimer)); + //WriteLog(pointFinal); + + loop(pointFinal){ + + CreateScoreItem(POINT_REGULAR, posEnm[0]+rand(-60, 60), posEnm[1]+rand(-60, 60)); + + } + + _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)); + + } + + _ScorePopup(posEnm[0], posEnm[1], "PIV", 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){ + + 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 = 75; + float yDes = 60; // Destination text object moves to, relative to enmY + string font = "Unispace"; + float borderSize = 6; + + if (type == "POINT"){ + + int pointText = CreateTextObject( + enmX, enmY, size, + "x" ~ IntToString(itemNum), font, + 0x7699FF, 0xFFFFFF, + 0x2A00C0, borderSize, + 42 + ); + ObjText_SetHorizontalAlignment(pointText, ALIGNMENT_CENTER); + + 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{ + int pivText = CreateTextObject( + enmX, enmY+offset, size, + "x" ~ IntToString(itemNum), font, + 0xFFB4EC, 0xFFFFFF, + 0xB200AD, borderSize, + 42 + ); + + ObjText_SetHorizontalAlignment(pivText, ALIGNMENT_CENTER); + + 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); + } + +} diff --git a/script/KevinSystem/kevin_system/Kevin_EndScene.txt b/script/KevinSystem/kevin_system/Kevin_EndScene.txt new file mode 100644 index 0000000..303df7f --- /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![r]Until the next pride..."); + ObjText_SetFontSize(objText, 36); + ObjText_SetFontType(objText, "Connecting Chain Handserif"); + + //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, 8*STGHEIGHT/9); + + 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, 65); + ObjText_SetFontType(obj, "Connecting Chain Handserif"); + 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 = ["End of a Journey"]; + int x = prand_int(0, length(textchoices)-1); + let objText = ObjText_Create(); + ObjText_SetText(objText, textchoices[x]); + ObjText_SetFontSize(objText, 150); + ObjText_SetFontType(objText, "Anke Calligraph"); + + //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, 100); + + let mx = GetScreenWidth/2; + let my = GetScreenHeight/4; + let texts = ["Save A Replay", "Depart From The Market", "Re-enter The Parade"]; + 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..2019ca2 --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_ItemConst.txt @@ -0,0 +1,13 @@ + +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; \ No newline at end of file diff --git a/script/KevinSystem/kevin_system/Kevin_ItemData.txt b/script/KevinSystem/kevin_system/Kevin_ItemData.txt new file mode 100644 index 0000000..68ed57c --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_ItemData.txt @@ -0,0 +1,16 @@ +#UserItemData + +item_image = "./../img/yo.png" + +ItemData { id=1 rect=(256,256,384,384) } // 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=(384,384,512,512) 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 \ 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..4c10846 --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_ItemLib.txt @@ -0,0 +1,146 @@ +// Valid types: PIV_100, PIV_250, PIV_500 + +float universalItemAlpha = GetAreaCommonData("Config", "ItemOpacity", 60); + +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; + +function CreatePIVItem(itemtype, x, y){ + + let PIVItem = CreateItemU1(itemtype, x, y, 0); + ObjItem_SetDefaultCollectMovement(PIVItem, false); + + async{ + wait(20); + ObjMove_SetMaxSpeed(PIVItem, 24); + ObjItem_SetMoveToPlayer(PIVItem, true); + } + + //ObjItem_SetAutoCollectEnableFlags(PIVItem, ITEM_AUTOCOLLECT_ALL); + + ObjItem_SetIntersectionRadius(PIVItem, 60); + + ObjRender_SetScaleXYZ(PIVItem, 0.85, 0.85, 1); + ObjRender_SetAlpha(PIVItem, 255*(universalItemAlpha/100)); + + async{ + while(!Obj_IsDeleted(PIVItem)){ + float angz = ObjRender_GetAngleZ(PIVItem); + ObjRender_SetAngleZ(PIVItem, angz+3.5); + yield; + } + } + + return PIVItem; +} + +// 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); + + async{ + wait(45); + ObjItem_SetMoveToPlayer(ScoreItem, true); + } + + //ObjItem_SetAutoCollectEnableFlags(ScoreItem, ITEM_AUTOCOLLECT_ALL); + + ObjItem_SetIntersectionRadius(ScoreItem, 60); + ObjItem_SetRenderScoreEnable(ScoreItem, false); + + //ObjRender_SetScaleXYZ(ScoreItem, 0.7, 0.7, 1); + ObjRender_SetAlpha(ScoreItem, 255*(universalItemAlpha/100)); + + //ObjMove_AddPatternA2(ScoreItem, 60, NO_CHANGE, 90, 0.12, 5.45, 0); + + 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); + + ObjRender_SetScaleXYZ(ExtendItem, 1.5, 1.5, 1); + Obj_SetRenderPriorityI(ExtendItem, 49); + + 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..8a12c3f --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_Pause.txt @@ -0,0 +1,298 @@ +//一時停止中スクリプト +//#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 = [ + "The sun is just a really hot egg tart, if you think about it.", + "Gay people.", + "You know what else is as cool as gay Touhous? It's Kouji Kouda[r]from the hit anime \"Boku no Hero Academia\"- *turns into a Kouda plushie*", + "Thanks for playing this game! I hope you enjoyed my gay Touhou endeavours.", + "You can set the amount of starting lives you have in the configurations menu.[r]If you have trouble with difficult patterns or stage sections, now you can blast right through them!" + ]; + int x = prand_int(0, length(textchoices)-1); + //y = length(textchoices); + + let objText = ObjText_Create(); + ObjText_SetText(objText, textchoices[x]); + ObjText_SetFontSize(objText, 36); + ObjText_SetFontType(objText, "Connecting Chain Handserif"); + + //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, 8*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, 65); + ObjText_SetFontType(obj, "Connecting Chain Handserif"); + 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 = ["Market Moratorium", "Respite from the Parade", "Worthy Rest"]; + int x = prand_int(0, length(textchoices)-1); + let objText = ObjText_Create(); + ObjText_SetText(objText, textchoices[x]); + ObjText_SetFontSize(objText, 150); + ObjText_SetFontType(objText, "Anke Calligraph"); + + //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, 100); + + let mx = GetScreenWidth/2; + let my = GetScreenHeight/4; + let texts = ["Resume The Faceoff", "Accept Your Losses", "Take Another Shot"]; + 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..121540b --- /dev/null +++ b/script/KevinSystem/kevin_system/Kevin_ReplaySave.txt @@ -0,0 +1,421 @@ +//リプレイ保存スクリプト + +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 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 = 20; + let pageMax = trunc((countMaxItem - 1) / countItemPerPage); + pageMax = max(pageMax, 1); + let lastPageMaxCursorY = trunc(countMaxItem / countItemPerPage); + + task TMenuItem(let itemY) + { + let objText = CreateTextObject(90, 45 + 50 * itemY, 35, ""); + let objSelect = CreateTextObject(90, 45 + 50 * itemY, 35, ""); + 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 ~ rtos("000000000000", GetReplayInfo(index, REPLAY_TOTAL_SCORE)) ~ " "; + text = text ~ GetReplayInfo(index, REPLAY_PLAYER_NAME) ~ " "; + text = text ~ GetReplayUserData(index, "Difficulty"); + + /*SetReplayUserData("Starting Lives", GetCommonData("Starting Lives Selected", 5)); + SetReplayUserData("Player Team", GetReplayInfo(index, REPLAY_PLAYER_NAME)); + SetReplayUserData("Difficulty", GetCommonData("Difficulty", "Arcade"));*/ + + } + 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(360 + GetStgFrameWidth()/4 + itemX * 42, 400 + itemY * 42, 40, strTextView[itemY][itemX]); + let objSelect = CreateTextObject(360 + 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(360+GetStgFrameWidth()/4, 200, 45, ""); + task TNameCursor() + { + let objCursor = CreateTextObject(360+GetStgFrameWidth()/4, 200, 45, "_"); + while(menuMode == MENU_NAME_ENTRY) + { + let nameLength = length(userName); + ObjRender_SetX(objCursor, 360+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", "Arcade")); + 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/Legacy (1280x720)/KevinSystem_Item.txt b/script/KevinSystem/kevin_system/Legacy (1280x720)/KevinSystem_Item.txt new file mode 100644 index 0000000..b23af13 --- /dev/null +++ b/script/KevinSystem/kevin_system/Legacy (1280x720)/KevinSystem_Item.txt @@ -0,0 +1,46 @@ +// Item script + +#include "./Kevin_ItemConst.txt" +#include "./Kevin_ItemLib.txt" +//#include "./Kevin_ItemData.txt" + +@Initialize{ + SetAutoDeleteObject(true); + SetDefaultBonusItemEnable(true); + LoadItemData(GetCurrentScriptDirectory ~ "./Kevin_ItemData.txt"); +} + +@MainLoop{ + yield; +} + +@Event +{ + alternative (GetEventType) + case (EV_GET_ITEM){ + + let obj = GetEventArgument(0); + + alternative(obj) + + case(POINT_REGULAR){ AddScore(GetAreaCommonData("PIV", "currentvalue", 0));} + case(POINT_BHESTIE){ AddScore(2*GetAreaCommonData("PIV", "currentvalue", 0));} + case(EXTEND_LIFE){ AddScore(50000); SetPlayerLife(GetPlayerLife()+1);} + case(EXTEND_SPELL){ AddScore(50000); SetPlayerSpell(GetPlayerSpell()+1);} + case(PIV_100){ SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue", 0)+100);} + case(PIV_250){ SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue", 0)+250);} + case(PIV_500){ SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue", 0)+500);} + + } + + case (EV_DELETE_SHOT_TO_ITEM){ + + } + + case (EV_COLLECT_ITEM){ + let obj = GetEventArgument(1); + ObjMove_SetAcceleration(obj, 0.85); + ObjMove_SetMaxSpeed(obj, 12); + } + +} \ No newline at end of file diff --git a/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_EndScene.txt b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_EndScene.txt new file mode 100644 index 0000000..1717c91 --- /dev/null +++ b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_EndScene.txt @@ -0,0 +1,292 @@ +//一時停止中スクリプト + +#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 clearText = ObjText_Create(); + ObjText_SetText(clearText, "Congratulations on clearing the game![r]Until the next convocation..."); + ObjText_SetFontSize(clearText, 18.5); + ObjText_SetFontType(clearText, "Connecting Chain Handserif"); + + ObjText_SetMaxWidth(clearText, STGWIDTH); + ObjText_SetHorizontalAlignment(clearText, ALIGNMENT_CENTER); + + ObjText_SetFontBold(clearText, true); + ObjText_SetFontColorTop(clearText, 255, 255, 255); + ObjText_SetFontColorBottom(clearText, 255, 255, 255); + ObjText_SetFontBorderType(clearText, BORDER_FULL); + ObjText_SetFontBorderColor(clearText, 0x7D39D9); + ObjText_SetFontBorderWidth(clearText, 2); + Obj_SetRenderPriorityI(clearText, 10); + ObjRender_SetX(clearText, STGWIDTH-255); + ObjRender_SetY(clearText, STGHEIGHT-75); + + // Render semi-transparent primitive background + task TRenderPrim(selection){ + + // Thank you for the PrimMaker Ferase :omegaflooshed: + + ObjRender_SetPosition(selection, renderX+640, renderY+360, 0); // Since the render priority of the r.target is under 20 + + // Set up vert 0 + ObjPrim_SetVertexPosition(selection,0,-640,-360,0); + ObjPrim_SetVertexColor(selection,0,0xA487FF); + ObjPrim_SetVertexUVT(selection, 0, 0, 0); + // Set up vert 1 + ObjPrim_SetVertexPosition(selection,1,640,-360,0); + ObjPrim_SetVertexColor(selection,1,0xA487FF); + ObjPrim_SetVertexUVT(selection, 1, 1280, 0); + // Set up vert 2 + ObjPrim_SetVertexPosition(selection,2,640,360,0); + ObjPrim_SetVertexColor(selection,2,0xA487FF); + ObjPrim_SetVertexUVT(selection, 2, 1280, 720); + // Set up vert 3 + ObjPrim_SetVertexPosition(selection,3,640,360,0); + ObjPrim_SetVertexColor(selection,3,0xF187FF); + ObjPrim_SetVertexUVT(selection, 3, 1280, 720); + // Set up vert 4 + ObjPrim_SetVertexPosition(selection,4,-640,360,0); + ObjPrim_SetVertexColor(selection,4,0xF187FF); + ObjPrim_SetVertexUVT(selection, 4, 0, 720); + // Set up vert 5 + ObjPrim_SetVertexPosition(selection,5,-640,-360,0); + ObjPrim_SetVertexColor(selection,5,0xF187FF); + ObjPrim_SetVertexUVT(selection, 5, 0, 0); + + for(int i = 0; i <= 5; i++){ + ObjPrim_SetVertexAlpha(selection, i, 100); + } + } + + // Render... the render target??? + let objBG = ObjPrim_Create(OBJ_PRIMITIVE_2D); + ObjPrim_SetPrimitiveType(objBG, PRIMITIVE_TRIANGLELIST); + ObjPrim_SetVertexCount(objBG, 6); + let target = "target"; + CreateRenderTargetEx(target, 1280, 720); + ObjPrim_SetTexture(objBG, target); + //SetInvalidRenderPriorityA1(20, 80); + RenderToTextureA1(target, 0, 100, true); + //RenderToTextureB1(target, objBG, true); + Obj_SetRenderPriorityI(objBG, 0); + TRenderPrim(objBG); + +} + +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;//選択位置 + task 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, 35); + ObjText_SetFontType(obj, "Exotc350 DmBd BT"); + 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, 1.75); + 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); + loop + { + Obj_SetVisible(objSelect, index == selectIndex); + yield; + } + } + + //メニュー配置 + let objText = ObjText_Create(); + ObjText_SetText(objText, "End of a Duel"); + ObjText_SetFontSize(objText, 50); + ObjText_SetFontType(objText, "Exotc350 DmBd BT"); + + 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, STGWIDTH-255); + ObjRender_SetY(objText, 100); + + let mx = STGWIDTH-255; + let my = 175; + let texts = ["Record Your Victories", "Leave The Battlefield", "Go For A Rematch"]; + var countMenu = length(texts); + ascent(var iText in 0 .. countMenu) + { + TMenuItem(iText, mx, my, texts[iText]); + my += 45; + } + + //キー状態がリセットされるまで待機 + while(GetVirtualKeyState(VK_OK) != KEY_FREE){yield;} + + //メニュー選択処理 + let frameKeyHold = 0;//キー押しっぱなしフレーム数 + loop + { + //決定 + if(GetVirtualKeyState(VK_OK) == KEY_PULL) + { + let listResult = [RESULT_SAVE_REPLAY, RESULT_END, RESULT_RETRY]; + SetScriptResult(listResult[selectIndex]); + 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; + } + + yield; + } +} + + + diff --git a/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ItemConst.txt b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ItemConst.txt new file mode 100644 index 0000000..c951481 --- /dev/null +++ b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ItemConst.txt @@ -0,0 +1,7 @@ +const POINT_REGULAR = 1; +const POINT_BHESTIE = 2; +const EXTEND_LIFE = 3; +const EXTEND_SPELL = 4; +const PIV_100 = 5; +const PIV_250 = 6; +const PIV_500 = 7; \ No newline at end of file diff --git a/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ItemData.txt b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ItemData.txt new file mode 100644 index 0000000..f32d9bb --- /dev/null +++ b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ItemData.txt @@ -0,0 +1,11 @@ +#UserItemData + +item_image = "./../img/yo.png" + +ItemData { id=1 rect=(256,256,384,384) } // Regular Point Item (PIV) +ItemData { id=2 rect=(384,128,512,256) } // Bhestie Point Item (PIV * 2) +ItemData { id=3 rect=(0,256,128,384) } // 1-up Item +ItemData { id=4 rect=(128,256,256,384) } // Spell Item +ItemData { id=5 rect=(256,384,384,512) fixed_angle = false angular_velocity = 3} // Green PIV Item (+100) +ItemData { id=6 rect=(384,384,512,512) fixed_angle = false angular_velocity = 3} // Pink PIV Item (+250) +ItemData { id=7 rect=(384,256,512,384) fixed_angle = false angular_velocity = 3} // Gold PIV Item (+500) diff --git a/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ItemLib.txt b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ItemLib.txt new file mode 100644 index 0000000..777d751 --- /dev/null +++ b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ItemLib.txt @@ -0,0 +1,92 @@ +// Valid types: PIV_100, PIV_250, PIV_500 + +function CreatePIVItem(itemtype, x, y){ + let PIVItem = CreateItemU2(itemtype, x, y, x-10, y-10, 100); + + ObjItem_SetMoveToPlayer(PIVItem, true); + ObjItem_SetAutoDelete(PIVItem, false); + + ObjItem_SetAutoCollectEnableFlags(PIVItem, ITEM_AUTOCOLLECT_ALL); + ObjItem_SetRenderScoreEnable(PIVItem, false); + + ObjItem_SetIntersectionRadius(PIVItem, 60); + + ObjRender_SetScaleXYZ(PIVItem, 0.3, 0.3, 1); + ObjRender_SetAlpha(PIVItem, 125); + + async{ + while(!Obj_IsDeleted(PIVItem)){ + float angz = ObjRender_GetAngleZ(PIVItem); + ObjRender_SetAngleZ(PIVItem, angz+5); + yield; + } + } + + return PIVItem; +} + +// Valid types: POINT_REGULAR, POINT_BHESTIE +function CreateScoreItem(itemtype, x, y){ + let ScoreItem = CreateItemU2(itemtype, x, y, x-30, y-30, 0); + + ObjItem_SetAutoCollectEnableFlags(ScoreItem, ITEM_AUTOCOLLECT_ALL); + ObjItem_SetAutoDelete(ScoreItem, false); + + ObjItem_SetIntersectionRadius(ScoreItem, 60); + ObjItem_SetRenderScoreEnable(ScoreItem, false); + + ObjRender_SetScaleXYZ(ScoreItem, 0.4, 0.4, 1); + ObjRender_SetAlpha(ScoreItem, 200); + + ObjMove_AddPatternA2(ScoreItem, 60, NO_CHANGE, 90, 0.12, 5.45, 0); + + return ScoreItem; +} + +// Valid types: EXTEND_LIFE, EXTEND_SPELL +function CreateExtendItem(itemtype, x, y){ + + let ExtendItem = CreateItemU2(itemtype, x, y, x-15, y-15, 0); + ObjItem_SetMoveToPlayer(ExtendItem, true); + ObjItem_SetAutoCollectEnableFlags(ExtendItem, ITEM_AUTOCOLLECT_ALL); + + ObjRender_SetScaleXYZ(ExtendItem, 0.5, 0.5, 1); + + 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{} + +} \ No newline at end of file diff --git a/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_Pause.txt b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_Pause.txt new file mode 100644 index 0000000..5eaa64e --- /dev/null +++ b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_Pause.txt @@ -0,0 +1,335 @@ +//一時停止中スクリプト +//#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 = [ + "Even though her parents gave her an entire crash course[r]on how royals enjoy tea, Erika is more a coffee fan.", + "Pankevin is terrified of heights, but loves rollercoasters & thrill rides.[r]He only rides the ones with shoulder harnesses to feel safer,[r]and always goes with Kouda.", + "Rachel has been exterminated at least twice by Housui[r]for constantly nagging her to let Rachel experiment.", + "There are a total of 18 fun facts on this pause menu,[r]including this one. How many have you found?", + "The creator of this game is incredibly self-indulgent.[r]You probably figured out this one, though...", + "Connecting Chain Handserif is the creator's favorite font.[r]As a Brazilian once said, \"this bitch is[r]hyperfixated on that font\".", + "Pankevin is acquainted with a duck who casts ice magic in the[r]Outside World. His name is Caleb.", + "Marisa and Housui often duel in the Forest of Magic.[r]Their antics have incited Alice's wrath so much that[r]she just doesn't care anymore.", + "Whenever Tenshi and Shion organize banquets at the Hakurei Shrine,[r]Erika is the self-appointed taste tester of the food.[r]It's gone from \"unbearable\" to \"passable\" according to her.", + "Kouda always has a pair of fluffy cat-ear headphones on hand wherever[r]he goes, so he can plop them on when he's overwhelmed by loud sounds.[r]Pankevin keeps the headphones for Kouda in his huge quiver[r]when they're traveling together.", + "Tenshi and Erika were planning to bring Shion along for[r]their adventures, but the latter was exhausted after[r]the oil overflow incident and stayed out.[r](If Shion came along, they would be too powerful...)", + "Housui's favorite food are amarylis flowers.[r]...That's what she says, but it's probably just mochi.", + "Inside Pankevin's huge quiver, there are many refillable water containers,[r]a portable sketchbook & watercolor set, some snacks, and a pair of[r]fluffy cat-ear headphones for Kouda.", + "Pankevin = Panda + Kevin, not Pansexual x Kevin. Pankevin is bi.", + "Thank you for playing this game! It means a lot to me :D", + "Erika Rankyuu debuted in the creator's first game, Enigma of the Storm. [r]It was made for a bullet hell game contest in a Discord server.", + "Housui Henkawa debuted in Unstable and Unimaginable Power, [r]a Touhou fangame. It's very well-crafted and polished, so go ahead[r]and play it! Housui's the Extra boss, by the way.", + "Housui is not bald.", + ]; + int x = prand_int(0, length(textchoices)-1); + //y = length(textchoices); + + let objText = ObjText_Create(); + ObjText_SetText(objText, textchoices[x]); + ObjText_SetFontSize(objText, 18.5); + ObjText_SetFontType(objText, "Connecting Chain Handserif"); + + ObjText_SetMaxWidth(objText, STGWIDTH); + 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, STGWIDTH-255); + ObjRender_SetY(objText, STGHEIGHT-75); + +} + +// renderX and renderY will be TOP-LEFT COORDS +task TBackgroundNew(renderX, renderY){ + // Render semi-transparent primitive background + task TRenderPrim(selection){ + + // Thank you for the PrimMaker Ferase :omegaflooshed: + + ObjRender_SetPosition(selection, renderX+640, renderY+360, 0); // Since the render priority of the r.target is under 20 + + // Set up vert 0 + ObjPrim_SetVertexPosition(selection,0,-640,-360,0); + ObjPrim_SetVertexColor(selection,0,0xA487FF); + ObjPrim_SetVertexUVT(selection, 0, 0, 0); + // Set up vert 1 + ObjPrim_SetVertexPosition(selection,1,640,-360,0); + ObjPrim_SetVertexColor(selection,1,0xA487FF); + ObjPrim_SetVertexUVT(selection, 1, 1280, 0); + // Set up vert 2 + ObjPrim_SetVertexPosition(selection,2,640,360,0); + ObjPrim_SetVertexColor(selection,2,0xA487FF); + ObjPrim_SetVertexUVT(selection, 2, 1280, 720); + // Set up vert 3 + ObjPrim_SetVertexPosition(selection,3,640,360,0); + ObjPrim_SetVertexColor(selection,3,0xF187FF); + ObjPrim_SetVertexUVT(selection, 3, 1280, 720); + // Set up vert 4 + ObjPrim_SetVertexPosition(selection,4,-640,360,0); + ObjPrim_SetVertexColor(selection,4,0xF187FF); + ObjPrim_SetVertexUVT(selection, 4, 0, 720); + // Set up vert 5 + ObjPrim_SetVertexPosition(selection,5,-640,-360,0); + ObjPrim_SetVertexColor(selection,5,0xF187FF); + ObjPrim_SetVertexUVT(selection, 5, 0, 0); + + for(int i = 0; i <= 5; i++){ + ObjPrim_SetVertexAlpha(selection, i, 100); + } + } + + // Render... the render target??? + let objBG = ObjPrim_Create(OBJ_PRIMITIVE_2D); + ObjPrim_SetPrimitiveType(objBG, PRIMITIVE_TRIANGLELIST); + ObjPrim_SetVertexCount(objBG, 6); + let target = "target"; + CreateRenderTargetEx(target, 1280, 720); + ObjPrim_SetTexture(objBG, target); + //SetInvalidRenderPriorityA1(20, 80); + RenderToTextureA1(target, 0, 100, true); + //RenderToTextureB1(target, objBG, true); + Obj_SetRenderPriorityI(objBG, 0); + TRenderPrim(objBG); + +} + +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;//選択位置 + task 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, 35); + ObjText_SetFontType(obj, "Exotc350 DmBd BT"); + 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, 1.75); + 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); + loop + { + Obj_SetVisible(objSelect, index == selectIndex); + yield; + } + } + + //メニュー配置 + int x = prand_int(0, 6); + let textchoices = ["A Brief Respite", "Yassification Paused", "Tea Time", "Heroic Moratorium", "World Comes to A Halt","A Moment to Breathe", "Players are Resting Warmly"]; + + let objText = ObjText_Create(); + ObjText_SetText(objText, textchoices[x]); + ObjText_SetFontSize(objText, 50); + ObjText_SetFontType(objText, "Exotc350 DmBd BT"); + + 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, STGWIDTH-255); + ObjRender_SetY(objText, 100); + + let mx = STGWIDTH-255; + let my = 175; + let texts = ["Resume The Faceoff", "Accept Your Losses", "Take Another Shot"]; + var countMenu = length(texts); + ascent(var iText in 0 .. countMenu) + { + TMenuItem(iText, mx, my, texts[iText]); + my += 45; + } + + //キー状態がリセットされるまで待機 + 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; + } + + yield; + } +} + + + diff --git a/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ReplaySave.txt b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ReplaySave.txt new file mode 100644 index 0000000..34feff8 --- /dev/null +++ b/script/KevinSystem/kevin_system/Legacy (1280x720)/Kevin_ReplaySave.txt @@ -0,0 +1,453 @@ +//リプレイ保存スクリプト + +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 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_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, 1.75); + Obj_SetRenderPriorityI(obj, 10); + ObjRender_SetX(obj, mx); + ObjRender_SetY(obj, my); + return obj; +} + +// renderX and renderY will be TOP-LEFT COORDS +task TBackgroundNew(renderX, renderY){ + // Render semi-transparent primitive background + task TRenderPrim(selection){ + + // Thank you for the PrimMaker Ferase :omegaflooshed: + + ObjRender_SetPosition(selection, renderX+640, renderY+360, 0); // Since the render priority of the r.target is under 20 + + // Set up vert 0 + ObjPrim_SetVertexPosition(selection,0,-640,-360,0); + ObjPrim_SetVertexColor(selection,0,0xA487FF); + ObjPrim_SetVertexUVT(selection, 0, 0, 0); + // Set up vert 1 + ObjPrim_SetVertexPosition(selection,1,640,-360,0); + ObjPrim_SetVertexColor(selection,1,0xA487FF); + ObjPrim_SetVertexUVT(selection, 1, 1280, 0); + // Set up vert 2 + ObjPrim_SetVertexPosition(selection,2,640,360,0); + ObjPrim_SetVertexColor(selection,2,0xA487FF); + ObjPrim_SetVertexUVT(selection, 2, 1280, 720); + // Set up vert 3 + ObjPrim_SetVertexPosition(selection,3,640,360,0); + ObjPrim_SetVertexColor(selection,3,0xF187FF); + ObjPrim_SetVertexUVT(selection, 3, 1280, 720); + // Set up vert 4 + ObjPrim_SetVertexPosition(selection,4,-640,360,0); + ObjPrim_SetVertexColor(selection,4,0xF187FF); + ObjPrim_SetVertexUVT(selection, 4, 0, 720); + // Set up vert 5 + ObjPrim_SetVertexPosition(selection,5,-640,-360,0); + ObjPrim_SetVertexColor(selection,5,0xF187FF); + ObjPrim_SetVertexUVT(selection, 5, 0, 0); + + for(int i = 0; i <= 5; i++){ + ObjPrim_SetVertexAlpha(selection, i, 100); + } + } + + // Render... the render target??? + let objBG = ObjPrim_Create(OBJ_PRIMITIVE_2D); + ObjPrim_SetPrimitiveType(objBG, PRIMITIVE_TRIANGLELIST); + ObjPrim_SetVertexCount(objBG, 6); + let target = "target"; + CreateRenderTargetEx(target, STGWIDTH, STGHEIGHT); + ObjPrim_SetTexture(objBG, target); + //SetInvalidRenderPriorityA1(20, 80); + RenderToTextureA1(target, 0, 100, true); + //RenderToTextureB1(target, objBG, true); + Obj_SetRenderPriorityI(objBG, 0); + TRenderPrim(objBG); + +} + +task TBackground +{ + let target = GetTransitionRenderTargetName(); + let obj = ObjPrim_Create(OBJ_SPRITE_2D); + ObjPrim_SetTexture(obj, target); + Obj_SetRenderPriority(obj, 0.1); + ObjSprite2D_SetSourceRect(obj, 0, 0, 640, 480); + ObjSprite2D_SetDestCenter(obj); + ObjRender_SetPosition(obj, 320, 240, 0); + ObjRender_SetAlpha(obj, 64); +} + +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(341, 90 + 30 * itemY, 25, ""); + let objSelect = CreateTextObject(341, 90 + 30 * itemY, 25, ""); + ObjRender_SetBlendType(objSelect, BLEND_ADD_RGB); + + 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 ~ rtos("000000000000", GetReplayInfo(index, REPLAY_TOTAL_SCORE)) ~ " "; + } + else + { + text = text ~ "No Data"; + } + 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_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(341 + GetStgFrameWidth()/5.4 + itemX * 24, 255 + itemY * 24, 22, strTextView[itemY][itemX]); + let objSelect = CreateTextObject(341 + GetStgFrameWidth()/5.4 + itemX * 24, 255 + itemY * 24, 22, 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(341+GetStgFrameWidth()/4, 125, 28, ""); + task TNameCursor() + { + let objCursor = CreateTextObject(341+GetStgFrameWidth()/4, 125, 28, "_"); + while(menuMode == MENU_NAME_ENTRY) + { + let nameLength = length(userName); + ObjRender_SetX(objCursor, 341+GetStgFrameWidth()/4 + nameLength * 17); + 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 = "No Name"; + } + else + { + 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/Legacy (1280x720)/ValueLib.txt b/script/KevinSystem/kevin_system/Legacy (1280x720)/ValueLib.txt new file mode 100644 index 0000000..e69de29 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/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..ba67736 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/Non1.dnh b/script/game/Non1.dnh new file mode 100644 index 0000000..9799779 --- /dev/null +++ b/script/game/Non1.dnh @@ -0,0 +1,285 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["Remilia Nonspell 1"] +#Text["yassification"] +#System["script/KevinSystem/Kevin_System.txt"] + +int difficultySelect = 0; + +let objScene = GetEnemyBossSceneObjectID(); +let csd = GetCurrentScriptDirectory(); + +let bossObj; + +float bossX = 0; +float bossY = 0; +float playerY = 0; +float playerX = 0; + +let aniframe = 0; +let aniframe2 = 0; + +let spellsnd = ObjSound_Create(); +let bossdiesnd = ObjSound_Create(); + +/*Parameters: + +- Density of red bubble spiral +- Delay between red bubble firing +- Speed of red bubbles + +- Density of each bullet curve +- Angle difference between each bullet in curve +- Density of blue spiral (how many curves in one spiral)? +- Delay of blue firing +- Speed of blue spiral*/ + +int[] denseBubble = [8, 9, 10]; +int[] delayBubble = [15, 12, 10]; +float[] speedBubble = [8, 9, 9]; + +int[] denseCurve = [5, 7, 7]; +float[] offsetCurve = [2, 2.8, 4.2]; +int[] denseSpiral = [6, 8, 9]; +int[] delaySpiral = [10, 8, 10]; +int[] speedSpiral = [6, 8, 8]; + + +// Includes ahoy + +#include "script/KevinSystem/Universal_Lib.txt" // The library to include all libraries :sans: :nail_care: + +@Initialize { + + //SetIntersectionVisualization(true); + + SetAutoDeleteObject(true); + + _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, GetCommonData("Boss Position X", STG_WIDTH/2), GetCommonData("Boss Position Y", STG_HEIGHT/2)); + ObjEnemy_SetMaximumDamage(bossObj, 999); + + // PLACEHOLDER! + let imgExRumia = GetModuleDirectory() ~ "script/ExRumia/ExRumia.png"; + ObjPrim_SetTexture(bossObj, imgExRumia); + ObjSprite2D_SetSourceRect(bossObj, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(bossObj); + ObjRender_SetScaleXYZ(bossObj, 2, 2, 1); + ObjRender_SetColor(bossObj, 0xB93C3C); + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, 550, 1); + // PLACEHOLDER! + + /*_SoloCutin( + "script/invalid.png", + 0, 0, 1, 1, + bossObj, objScene, "\"Euphoric Blooming of a New Market\"", + 40, 4, 0x2868B9, 0x1D115D, + 10, STG_HEIGHT*1/10-30, 41 + );*/ + + //WriteLog(spellPIV); + WriteLog(ObjEnemyBossScene_GetInfo(objScene, INFO_SPELL_SCORE)); + + mainTask(); + _FadeInvincibility(bossObj, 150, 150, 1); + endingnew(); +} + +@Event { + + alternative(GetEventType()) + + case(EV_REQUEST_LIFE) { + SetScriptResult(3000); + } + + case(EV_REQUEST_TIMER) { + SetScriptResult(25); + } + +} + +@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), 100); + + yield; + +} + +@Finalize { + +} + +/*Nonspell 1: + +Reference to Remi non 1 from EoSD. +Remi fires a light spiral of red bubbles while also firing a spiral of blue bullet curves in reverse. + +Parameters: + +- Density of red bubble spiral +- Delay between red bubble firing +- Speed of red bubbles + +- Density of each bullet curve +- Angle difference between each bullet in curve +- Density of blue spiral (how many curves in one spiral)? +- Delay of blue firing +- Speed of blue spiral + +*/ + +task mainTask { + + MoveToPosition(); + FireBubble(); + FireSpiral(); + +} + +function MoveToPosition(){ + + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, STG_HEIGHT/6+30, 90, LERP_DECELERATE); + wait(90); + +} + +task FireBubble(){ + + float ang = GetAngleToPlayer(bossObj); + int multiplier = 1; + + if(difficultySelect < 1){ + while(!ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){ + + loop(8){ + ascent(i in 0..denseBubble[difficultySelect]){ + int shot = CreateShotA1(bossX, bossY, speedBubble[difficultySelect], ang + 360/(denseBubble[difficultySelect])*i, KEV_BUBBLE_RED, 0); + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(shot);} + else{ + _Delay(shot, 10); + _BulletRescale(shot, 0.65, true, 1); + Shoot2; + } + } + + wait(delayBubble[difficultySelect]); + + ang += (360/(denseBubble[difficultySelect]))/3; + } + + ang = GetAngleToPlayer(bossObj); + + } + } + + else{ + while(!ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){ + + loop(8){ + ascent(i in 0..denseBubble[difficultySelect]){ + int shot = CreateShotA1(bossX, bossY, speedBubble[difficultySelect], ang + 360/(denseBubble[difficultySelect])*i, KEV_BUBBLE_RED, 0); + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(shot);} + else{ + _Delay(shot, 10); + _BulletRescale(shot, 0.65, true, 1); + Shoot2; + } + } + + wait(delayBubble[difficultySelect]); + + ang += (360/(denseBubble[difficultySelect]))/3*multiplier; + } + + ang = GetAngleToPlayer(bossObj); + multiplier *= -1; + + } + } + +} + +task FireSpiral(){ + + float startAng = 0; + float startAngWhole = 0; + int multiplier = 1; + + while(!ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){ + + startAngWhole = GetAngleToPlayer(bossObj); + startAng = startAngWhole; + + loop(5){ + + ascent(i in 0..denseCurve[difficultySelect]){ + + startAng -= offsetCurve[difficultySelect]*multiplier; + + ascent(j in -1..denseSpiral[difficultySelect]){ + + float ang = startAng + (360/denseSpiral[difficultySelect])*j; + int bullet = CreateShotA1(bossX, bossY, speedSpiral[difficultySelect], ang, KEV_BALL_AQUA, 5); + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){Obj_Delete(bullet);} + else{ + _Delay(bullet, 5); + _BulletRescale(bullet, 0.6, true, 1); + Obj_SetRenderPriorityI(bullet, 51); + ObjRender_SetBlendType(bullet, BLEND_ALPHA); + } + + } + + //Shoot2; + wait(2); + + } + + startAng -= (360/(denseSpiral[difficultySelect]))/2; + + wait(delaySpiral[difficultySelect]); + if(difficultySelect >= 1){multiplier *= -1;} else {} // Special behaviour for Hyper/Unparalleled + + } + + } + +} + +task endingnew(){ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE)>0){ + yield; + } + + _GoToBrazil(objScene, bossObj, 12, 24); + wait(120); + ObjSound_SetVolumeRate(fire2, 20); + + CloseScript(GetOwnScriptID); + +} + + diff --git a/script/game/Non2.dnh b/script/game/Non2.dnh new file mode 100644 index 0000000..42adae9 --- /dev/null +++ b/script/game/Non2.dnh @@ -0,0 +1,364 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["Remilia Nonspell 2"] +#Text["yassification"] +#System["script/KevinSystem/Kevin_System.txt"] + +int difficultySelect = 0; + +let objScene = GetEnemyBossSceneObjectID(); +let csd = GetCurrentScriptDirectory(); + +let bossObj; + +float bossX = 0; +float bossY = 0; +float playerY = 0; +float playerX = 0; + +let aniframe = 0; +let aniframe2 = 0; + +let spellsnd = ObjSound_Create(); +let bossdiesnd = ObjSound_Create(); + +/*Parameters: + +// Trail Burst + +- Density of red bubble spiral +- Angular velocity of bubbles +- Speed of bubbles + +- Density of each bullet curve left behind +- Delay between each bullet in curve +- Delay between each bullet curve +- Movement speed of bullet curve + +- Delay between trail and aimed burst +*/ + +int[] denseTrailSpiral = [7, 8, 10]; +float[] wvelTrailBubble = [3, 4, 5]; +float[] spdTrailBubble = [13, 14, 16]; + +int[] denseTrailCurve = [1, 1, 1]; +int[] delayCurveIndividual = [0, 0, 0]; +int[] delayCurve = [8, 7, 6]; +float[] speedCurve = [5, 6, 7]; + +int[] delayTrailAimed = [110, 100, 90]; + +/* +// Aimed Burst + +- Density of red bubble spiral +- Angular velocity of bubbles +- Speed of bubbles + +- Delay between each bullet left behind +- Bullet acceleration +- Bullet max speed + +// Final Trail Burst + +See trail burst above but x2. +- Delay between the two trail burst +*/ + +int[] denseAimedSpiral = [9, 10, 11]; +float[] wvelAimedBubble = [1.25, 1.4, 1.75]; +float[] spdAimedBubble = [12, 14, 16]; + +int[] delayAimed = [11, 9, 7]; +float[] accelAimed = [6/60, 8/50, 10/40]; +float[] maxspdAimed = [7, 8, 9]; + +int[] delayBeforeAim = [40, 30, 20]; +int[] delayFinalBurst = [45, 35, 30]; +int[] thresholdStopSpin = [80, 70, 60]; + +// Includes ahoy + +#include "script/KevinSystem/Universal_Lib.txt" // The library to include all libraries :sans: :nail_care: + +@Initialize { + + //SetIntersectionVisualization(true); + + SetAutoDeleteObject(true); + + _InitDifficulty(difficultySelect); + + //difficultySelect = 1; // debug + + SetShotAutoDeleteClip(64, 64, 64, 64); + + 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, GetCommonData("Boss Position X", STG_WIDTH/2), GetCommonData("Boss Position Y", STG_HEIGHT/2)); + ObjEnemy_SetMaximumDamage(bossObj, 999); + + // PLACEHOLDER! + let imgExRumia = GetModuleDirectory() ~ "script/ExRumia/ExRumia.png"; + ObjPrim_SetTexture(bossObj, imgExRumia); + ObjSprite2D_SetSourceRect(bossObj, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(bossObj); + ObjRender_SetScaleXYZ(bossObj, 2, 2, 1); + ObjRender_SetColor(bossObj, 0xB93C3C); + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, 550, 1); + // PLACEHOLDER! + + /*_SoloCutin( + "script/invalid.png", + 0, 0, 1, 1, + bossObj, objScene, "\"Euphoric Blooming of a New Market\"", + 40, 4, 0x2868B9, 0x1D115D, + 10, STG_HEIGHT*1/10-30, 41 + );*/ + + //WriteLog(spellPIV); + WriteLog(ObjEnemyBossScene_GetInfo(objScene, INFO_SPELL_SCORE)); + + mainTask(); + _FadeInvincibility(bossObj, 150, 150, 1); + endingnew(); +} + +@Event { + + alternative(GetEventType()) + + case(EV_REQUEST_LIFE) { + SetScriptResult(3000); + } + + case(EV_REQUEST_TIMER) { + SetScriptResult(25); + } + +} + +@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), 100); + + yield; + +} + +@Finalize { + +} + +/*Nonspell 1: + +Reference to Remi final from EoSD (Red Magic/Scarlet Gensokyo). + +Fires red bubbles that leave behind trails of bullets. +See: My BHA5 script’s second nonspell + +Parameters: + +// Trail Burst + +- Density of red bubble spiral +- Angular velocity of bubbles +- Speed of bubbles + +- Density of each bullet curve left behind +- Delay between each bullet in curve +- Delay between each bullet curve +- Movement speed of bullet curve + +- Delay between trail and aimed burst + +// Aimed Burst + +- Density of red bubble spiral +- Angular velocity of bubbles +- Speed of bubbles + +- Delay between each bullet left behind +- Bullet acceleration +- Bullet max speed + +// Final Trail Burst + +See trail burst above but x2. +- Delay between the two trail burst + +*/ + +task mainTask { + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + + FireTrail(rand(1.5*STG_WIDTH/8, 2.5*STG_WIDTH/8)); + FireAimed(rand(6.5*STG_WIDTH/8, 7.5*STG_WIDTH/8)); + wait(delayTrailAimed[difficultySelect]/2); + FireAimed(rand(1.5*STG_WIDTH/8, 2.5*STG_WIDTH/8)); + FireTrail(rand(6.5*STG_WIDTH/8, 7.5*STG_WIDTH/8)); + wait(delayTrailAimed[difficultySelect]*1.25); + + } + +} + +function FireTrail(destX){ + + //float destX = rand(1.5*STG_WIDTH/8, 2.5*STG_WIDTH/8); + + ObjMove_SetDestAtFrame(bossObj, destX, STG_HEIGHT/4, 30, LERP_DECELERATE); + wait(30); + + float ang = GetAngleToPlayer(bossObj); + + loop(denseTrailSpiral[difficultySelect]){ + int shot = CreateShotA2(bossX, bossY, spdTrailBubble[difficultySelect], ang, 0, spdTrailBubble[difficultySelect], wvelTrailBubble[difficultySelect], KEV_BUBBLE_RED, 5); + + ObjMove_AddPatternA2(shot, thresholdStopSpin[difficultySelect], NO_CHANGE, NO_CHANGE, NO_CHANGE, NO_CHANGE, wvelTrailBubble[difficultySelect]*0.25); + + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(shot);} + else{ + _Delay(shot, 10); + _BulletRescale(shot, 0.85, true, 1); + Shoot1; + } + _ShotTrail(shot, ang); + ang += 360/denseTrailSpiral[difficultySelect]; + } + + wait(delayTrailAimed[difficultySelect]); + +} + +task _ShotTrail(shot, ang){ + + wait(10); + + int del = 5; + + async{ + ObjShot_SetAutoDelete(shot, false); + wait(thresholdStopSpin[difficultySelect]+30); + ObjShot_SetAutoDelete(shot, true); + } + + while(!Obj_IsDeleted(shot) && ObjMove_GetY(shot) <= STG_HEIGHT-30 && ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + + Shoot2; + loop(denseTrailCurve[difficultySelect]){ + float x2 = ObjMove_GetX(shot); + float y2 = ObjMove_GetY(shot); + let bullet = CreateShotA1(x2, y2, 0, ObjMove_GetAngle(shot), KEV_AURABALL_RED, 15); + + if(Obj_IsDeleted(shot)){Obj_Delete(bullet);} + + Obj_SetRenderPriorityI(bullet, Obj_GetRenderPriorityI(shot)+1); + ObjMove_AddPatternA2(bullet, 60, NO_CHANGE, NO_CHANGE, -accelAimed[difficultySelect], -speedCurve[difficultySelect], 0); + _BulletRescale(bullet, 0.7, true, 1); + _Delay(bullet, 15); + + wait(delayCurveIndividual[difficultySelect]); + + } + wait(delayCurve[difficultySelect]); + del += 5; + } + +} + +function FireAimed(destX){ + + //float destX = rand(6.5*STG_WIDTH/8, 7.5*STG_WIDTH/8); + + ObjMove_SetDestAtFrame(bossObj, destX, STG_HEIGHT/4, 30, LERP_DECELERATE); + wait(30); + + float ang = GetAngleToPlayer(bossObj); + + loop(denseAimedSpiral[difficultySelect]){ + int shot = CreateShotA2(bossX, bossY, spdAimedBubble[difficultySelect], ang, 0, spdAimedBubble[difficultySelect], -1*wvelAimedBubble[difficultySelect], KEV_BUBBLE_LAVENDER, 5); + + ObjMove_AddPatternA2(shot, thresholdStopSpin[difficultySelect], NO_CHANGE, NO_CHANGE, NO_CHANGE, NO_CHANGE, wvelTrailBubble[difficultySelect]*-0.25); // Stop spinning after a while + + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(shot);} + else{ + _Delay(shot, 10); + _BulletRescale(shot, 0.85, true, 1); + Shoot1; + } + _ShotAimed(shot, ang); + ang += 360/denseAimedSpiral[difficultySelect]; + } + + wait(delayTrailAimed[difficultySelect]); + +} + +task _ShotAimed(shot, ang){ + + wait(10); + + int del = 1; + + async{ + ObjShot_SetAutoDelete(shot, false); + wait(thresholdStopSpin[difficultySelect]+30); + ObjShot_SetAutoDelete(shot, true); + } + + while(!Obj_IsDeleted(shot) && ObjMove_GetY(shot) <= STG_HEIGHT-30 && ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + + Shoot2; + + float x2 = ObjMove_GetX(shot); + float y2 = ObjMove_GetY(shot); + let bullet = CreateShotA1(x2, y2, 0, ObjMove_GetAngle(shot), KEV_BUTTERFLY_LAVENDER, 15); + + if(Obj_IsDeleted(shot)){Obj_Delete(bullet);} + + Obj_SetRenderPriorityI(bullet, Obj_GetRenderPriorityI(shot)+1); + ObjMove_AddPatternA4(bullet, delayBeforeAim[difficultySelect]-del, NO_CHANGE, 0, accelAimed[difficultySelect], maxspdAimed[difficultySelect], 0, NO_CHANGE, GetPlayerObjectID()); + _BulletRescale(bullet, 0.85, true, 1); + _Delay(bullet, 15); + + wait(delayAimed[difficultySelect]); + del += 1; + } + + ObjMove_AddPatternA2(shot, 80, NO_CHANGE, NO_CHANGE, NO_CHANGE, NO_CHANGE, 0); // Stop spinning after a while + +} + +task endingnew(){ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE)>0){ + yield; + } + + _GoToBrazil(objScene, bossObj, 12, 24); + wait(120); + ObjSound_SetVolumeRate(fire2, 20); + + CloseScript(GetOwnScriptID); + +} + + diff --git a/script/game/Spell2.dnh b/script/game/Spell2.dnh new file mode 100644 index 0000000..1a05d0b --- /dev/null +++ b/script/game/Spell2.dnh @@ -0,0 +1,202 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["Remilia Spell 2 (Patchouli Card)"] +#Text["yassification"] +#System["script/KevinSystem/Kevin_System.txt"] + +int difficultySelect = 0; + +let objScene = GetEnemyBossSceneObjectID(); +let csd = GetCurrentScriptDirectory(); + +let bossObj; + +float bossX = 0; +float bossY = 0; +float playerY = 0; +float playerX = 0; + +let aniframe = 0; +let aniframe2 = 0; + +let spellsnd = ObjSound_Create(); +let bossdiesnd = ObjSound_Create(); + +/* +Parameters: + +- Movement speed (in frames) +- Ring density +- Ring speed + +- Density of one knife line +- Speed of knives + +- Number of knife rings +- Density of each knife ring +- Speed of each knife ring +*/ + +int[] frameMove = [9*27, 9*25, 9*23]; // Divisible by 9 +int[] denseRing = [15, 18, 21]; +int[] speedRing = [4, 5, 6]; + +int[] denseKnifeLine = [5, 6, 7]; +float[] speedKnife = [8, 9, 10]; +float[] spaceKnifeFan = [5, 7, 9]; + +int[] ringcountKnife = [3, 5, 7]; +int[] ringdenseKnife = [10, 12, 14]; +float[] ringspeedKnife = [8, 9, 10]; + +// Includes ahoy + +#include "script/KevinSystem/Universal_Lib.txt" // The library to include all libraries :sans: :nail_care: + +@Initialize { + + //SetIntersectionVisualization(true); + + SetAutoDeleteObject(true); + + _InitDifficulty(difficultySelect); + + difficultySelect = 0; // debug + + SetShotAutoDeleteClip(64, 64, 64, 64); + + 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, GetCommonData("Boss Position X", STG_WIDTH/2), GetCommonData("Boss Position Y", STG_HEIGHT/2)); + ObjEnemy_SetMaximumDamage(bossObj, 999); + + // PLACEHOLDER! + let imgExRumia = GetModuleDirectory() ~ "script/ExRumia/ExRumia.png"; + ObjPrim_SetTexture(bossObj, imgExRumia); + ObjSprite2D_SetSourceRect(bossObj, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(bossObj); + ObjRender_SetScaleXYZ(bossObj, 2, 2, 1); + ObjRender_SetColor(bossObj, 0xB93C3C); + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, 550, 1); + // PLACEHOLDER! + + /*_SoloCutin( + "script/invalid.png", + 0, 0, 1, 1, + bossObj, objScene, "\"Euphoric Blooming of a New Market\"", + 40, 4, 0x2868B9, 0x1D115D, + 10, STG_HEIGHT*1/10-30, 41 + );*/ + + //WriteLog(spellPIV); + WriteLog(ObjEnemyBossScene_GetInfo(objScene, INFO_SPELL_SCORE)); + + mainTask(); + _FadeInvincibility(bossObj, 150, 150, 1); + endingnew(); +} + +@Event { + + alternative(GetEventType()) + + case(EV_REQUEST_LIFE) { + SetScriptResult(5200); + } + + case(EV_REQUEST_TIMER) { + SetScriptResult(40); + } + +} + +@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), 100); + + yield; + +} + +@Finalize { + +} + +/* + +Spell 2 (Patchouli): + +Remilia summons 5 books (5 elements) (see Philosopher's Stone). These books move to the top of the screen and fire downwards lines that restrict horizontal movement. +Remilia constantly will charge down at the player's horizontal position, leaving behind red rings. The player must weave through the lines of the books. +After 3 charges, the books turn into bats that aim for the player, leaving trails of bullets in their wake. Remilia re-calls 5 books and then the pattern restarts. + +Note: Books = Enemies with no registered intersection + +Parameters: + +- Line density +- Line speed +- Line delay + +- Ring density +- Ring speed +- Remilia charge time +- Remilia charge delay + +*/ + +task mainTask { + + wait(45); + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + + } + +} + +/* +Fire: 0, 0, 256, 256 +Water: 256, 0, 512, 256 +Wood: 512, 0, 768, 256 +Metal: 768, 0, 1024, 256 +Earth: 1024, 0, 1280, 256 +*/ + +task _CreateBook( + int[] [rectLeft, rectTop, rectRight, rectBottom], + float scale + ){ + +} + +task endingnew(){ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE)>0){ + yield; + } + + _GoToBrazil(objScene, bossObj, 12, 24); + wait(120); + ObjSound_SetVolumeRate(fire2, 20); + + CloseScript(GetOwnScriptID); + +} + + diff --git a/script/game/Spell3.dnh b/script/game/Spell3.dnh new file mode 100644 index 0000000..6fed527 --- /dev/null +++ b/script/game/Spell3.dnh @@ -0,0 +1,371 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["Remilia Spell 3 (Sakuya Card)"] +#Text["yassification"] +#System["script/KevinSystem/Kevin_System.txt"] + +int difficultySelect = 0; + +let objScene = GetEnemyBossSceneObjectID(); +let csd = GetCurrentScriptDirectory(); + +let bossObj; + +float bossX = 0; +float bossY = 0; +float playerY = 0; +float playerX = 0; + +let aniframe = 0; +let aniframe2 = 0; + +let spellsnd = ObjSound_Create(); +let bossdiesnd = ObjSound_Create(); + +/* +Parameters: + +- Movement speed (in frames) +- Ring density +- Ring speed + +- Density of one knife line +- Speed of knives + +- Number of knife rings +- Density of each knife ring +- Speed of each knife ring +*/ + +int[] frameMove = [9*27, 9*25, 9*23]; // Divisible by 9 +int[] denseRing = [15, 18, 21]; +int[] speedRing = [4, 5, 6]; + +int[] denseKnifeLine = [5, 6, 7]; +float[] speedKnife = [8, 9, 10]; +float[] spaceKnifeFan = [5, 7, 9]; + +int[] ringcountKnife = [3, 5, 7]; +int[] ringdenseKnife = [10, 12, 14]; +float[] ringspeedKnife = [8, 9, 10]; + +// Includes ahoy + +#include "script/KevinSystem/Universal_Lib.txt" // The library to include all libraries :sans: :nail_care: + +@Initialize { + + //SetIntersectionVisualization(true); + + SetAutoDeleteObject(true); + + _InitDifficulty(difficultySelect); + + difficultySelect = 0; // debug + + SetShotAutoDeleteClip(64, 64, 64, 64); + + 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, GetCommonData("Boss Position X", STG_WIDTH/2), GetCommonData("Boss Position Y", STG_HEIGHT/2)); + ObjEnemy_SetMaximumDamage(bossObj, 999); + + // PLACEHOLDER! + let imgExRumia = GetModuleDirectory() ~ "script/ExRumia/ExRumia.png"; + ObjPrim_SetTexture(bossObj, imgExRumia); + ObjSprite2D_SetSourceRect(bossObj, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(bossObj); + ObjRender_SetScaleXYZ(bossObj, 2, 2, 1); + ObjRender_SetColor(bossObj, 0xB93C3C); + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, 550, 1); + // PLACEHOLDER! + + /*_SoloCutin( + "script/invalid.png", + 0, 0, 1, 1, + bossObj, objScene, "\"Euphoric Blooming of a New Market\"", + 40, 4, 0x2868B9, 0x1D115D, + 10, STG_HEIGHT*1/10-30, 41 + );*/ + + //WriteLog(spellPIV); + WriteLog(ObjEnemyBossScene_GetInfo(objScene, INFO_SPELL_SCORE)); + + mainTask(); + _FadeInvincibility(bossObj, 150, 150, 1); + endingnew(); +} + +@Event { + + alternative(GetEventType()) + + case(EV_REQUEST_LIFE) { + SetScriptResult(5200); + } + + case(EV_REQUEST_TIMER) { + SetScriptResult(40); + } + +} + +@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), 100); + + yield; + +} + +@Finalize { + +} + +/* + +Spell 3 (Sakuya): + +Remilia moves to the horizontal middle and starts slowly moving from top to bottom, firing slow red rings. As she moves, she fires bursts of knives to the sides that reflect off the walls towards the player (one burst per 3 rings). +When she reaches the bottom, she fires a large burst of knives everywhere, following the same reflecting formula. + +Parameters: + +- Movement speed (in frames) +- Ring density +- Ring speed + +- Density of one knife line +- Speed of knives + +- Number of knife rings +- Density of each knife ring +- Speed of each knife ring + +*/ + +task mainTask { + + _Warn(); + wait(45); + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + + MoveToBottom(); + //BurstAttack(); + //wait(360); + wait(frameMove[difficultySelect]*2); + } + +} + +task _Warn(){ + + int time = 30; + int timeDisappear = 45; + + int pointText = CreateTextObject( + STG_WIDTH/2, 5.5*STG_HEIGHT/6, 120, + "WATCH OUT!", "Exotc350 DmBd BT", + 0xFF6868, 0xFFFFFF, + 0x800E0E, 6, + 51 + ); + ObjText_SetHorizontalAlignment(pointText, ALIGNMENT_CENTER); + + ascent(i in 0..time){ + ObjRender_SetAlpha(pointText, Interpolate_Decelerate(0, 255, i/time)); + ObjRender_SetY(pointText, Interpolate_Decelerate(5.2*STG_HEIGHT/6, 5*STG_HEIGHT/6, i/time)); + yield; + } + + wait(30); + + ascent(i in 0..timeDisappear){ + ObjRender_SetAlpha(pointText, Interpolate_Decelerate(255, 0, i/timeDisappear)); + yield; + } + Obj_Delete(pointText); + +} + +function MoveToBottom(){ + + float x = GetPlayerX(); + + ObjMove_SetDestAtFrame(bossObj, x, STG_HEIGHT/7, 45, LERP_DECELERATE); + wait(60); + + // Anti-cheese + + async{ + loop(60){ + int shot = CreateShotA1(bossX, bossY, 15, rand(180, 360), KEV_BUBBLE_RED, 10); + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(shot);} + else{ + _Delay(shot, 10); + _BulletRescale(shot, 0.8, true, 1); + Shoot1; + } + yield; + } + } + + // Slow movement + + ObjMove_SetDestAtFrame(bossObj, x, 5.5*STG_HEIGHT/6, frameMove[difficultySelect], LERP_SMOOTHER); + + async{ + loop(9){ + + float ang = GetAngleToPlayer(bossObj); + float[] spawn = [bossX+rand(-30, 30), bossY+rand(-30, 30)]; + + ascent(i in -1..denseRing[difficultySelect]-1){ + int shot = CreateShotA2(spawn[0], spawn[1], speedRing[difficultySelect], ang+(360/denseRing[difficultySelect])*i, -speedRing[difficultySelect]/[30, 35, 40][difficultySelect], 0, KEV_AURABALL_RED, 10); + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(shot);} + else{ + ObjMove_AddPatternA2(shot, frameMove[difficultySelect]/1.5, NO_CHANGE, NO_CHANGE, speedRing[difficultySelect]/45, speedRing[difficultySelect], 0); + _Delay(shot, 10); + _BulletRescale(shot, 0.6, true, 1); + Shoot1; + } + } + + wait(frameMove[difficultySelect]/9); + } + + // If you're at bottom, you die. (Hyper and above) + + if(difficultySelect >= 0){ + loop(9){ + + float ang = GetAngleToPlayer(bossObj); + float[] spawn = [bossX+rand(-25, 25), bossY+rand(-25, 25)]; + + ascent(i in -1..denseRing[difficultySelect]-1){ + int shot = CreateShotA2(spawn[0], spawn[1], speedRing[difficultySelect]*2.5, ang+(360/denseRing[difficultySelect])*i, -speedRing[difficultySelect]*2.5/[30, 40, 45][difficultySelect], speedRing[difficultySelect]*[0.3, 0.2, 0.1][difficultySelect], KEV_KNIFE_RED, 10); + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(shot);} + else{ + ObjMove_AddPatternA2(shot, 90, NO_CHANGE, NO_CHANGE, speedRing[difficultySelect]/45, speedRing[difficultySelect]*[1.65, 1.4, 1.25][difficultySelect], 0); + _Delay(shot, 10); + ObjRender_SetBlendType(shot, BLEND_ADD_ARGB); + _BulletRescale(shot, 1.25, true, 1); + Shoot1; + if(difficultySelect >= 1){_ReflectToPlayer(shot);} + } + } + + wait(frameMove[difficultySelect]/36); + } + } + + } + + async{ + loop(3){ + + CreateFan(3, KEV_KNIFE_LAVENDER, denseKnifeLine[difficultySelect], + 0, spaceKnifeFan[difficultySelect], speedKnife[difficultySelect]/1.3, speedKnife[difficultySelect], 1.25, + PATTERN_FAN, true); + + CreateFan(3, KEV_KNIFE_LAVENDER, denseKnifeLine[difficultySelect], + 180, spaceKnifeFan[difficultySelect], speedKnife[difficultySelect]/1.3, speedKnife[difficultySelect], 1.25, + PATTERN_FAN, true); + + wait(frameMove[difficultySelect]/3); + } + } + +} + +function CreateFan (int way, int graphic, int stack, + float ang, float angspace, float spd1, float spd2, float scale, + int type, bool reflect){ + + int objPattern = ObjPatternShot_Create(); + + ObjPatternShot_SetParentObject(objPattern, bossObj); + + 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; + int[] arrayPattern = ObjPatternShot_FireReturn(objPattern); + + for each (int bullet in ref arrayPattern){ + _BulletRescale(bullet, scale, true, 1); + _Delay(bullet, 10); + _EnemyShotFade(bullet, 600, true, 2.5); // Placeholder + Obj_SetRenderPriorityI(bullet, 51); + if (reflect) {_ReflectToPlayer(bullet);} + } + + async{ + wait(600); + Obj_Delete(objPattern); + return; + } + + return objPattern; + +} + +task _ReflectToPlayer(int target){ + + ObjShot_SetAutoDelete(target, false); + + while(!Obj_IsDeleted(target)){ + if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) == 0){Obj_Delete(target); return;} + if (ObjMove_GetX(target) <= -15 || ObjMove_GetX(target) >= GetStgFrameWidth()+15){ + ObjMove_AddPatternA4(target, 0, NO_CHANGE, 0, NO_CHANGE, NO_CHANGE, 0, KEV_KNIFE_GREEN, GetPlayerObjectID()); + Shoot2; + ObjShot_SetAutoDelete(target, true); + break; + } + yield; + } + +} + +task endingnew(){ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE)>0){ + yield; + } + + _GoToBrazil(objScene, bossObj, 12, 24); + wait(120); + ObjSound_SetVolumeRate(fire2, 20); + + CloseScript(GetOwnScriptID); + +} + + diff --git a/script/game/Spell4.dnh b/script/game/Spell4.dnh new file mode 100644 index 0000000..25a8d7e --- /dev/null +++ b/script/game/Spell4.dnh @@ -0,0 +1,218 @@ +#TouhouDanmakufu[Single] +#ScriptVersion[3] +#Title["Remilia Spell 4 (Meiling Card)"] +#Text["yassification"] +#System["script/KevinSystem/Kevin_System.txt"] + +int difficultySelect = 0; + +let objScene = GetEnemyBossSceneObjectID(); +let csd = GetCurrentScriptDirectory(); + +let bossObj; + +float bossX = 0; +float bossY = 0; +float playerY = 0; +float playerX = 0; + +let aniframe = 0; +let aniframe2 = 0; + +let spellsnd = ObjSound_Create(); +let bossdiesnd = ObjSound_Create(); + +/*Parameters: + +// Trail Burst + +- Density of red bubble spiral +- Angular velocity of bubbles +- Speed of bubbles + +- Density of each bullet curve left behind +- Delay between each bullet in curve +- Delay between each bullet curve +- Movement speed of bullet curve + +- Delay between trail and aimed burst +*/ + +int[] denseTrailSpiral = [7, 8, 10]; +float[] wvelTrailBubble = [3, 4, 5]; +float[] spdTrailBubble = [13, 14, 16]; + +int[] denseTrailCurve = [1, 1, 1]; +int[] delayCurveIndividual = [0, 0, 0]; +int[] delayCurve = [8, 7, 6]; +float[] speedCurve = [5, 6, 7]; + +int[] delayTrailAimed = [110, 100, 90]; + +/* +// Aimed Burst + +- Density of red bubble spiral +- Angular velocity of bubbles +- Speed of bubbles + +- Delay between each bullet left behind +- Bullet acceleration +- Bullet max speed + +// Final Trail Burst + +See trail burst above but x2. +- Delay between the two trail burst +*/ + +int[] denseAimedSpiral = [9, 10, 11]; +float[] wvelAimedBubble = [1.25, 1.4, 1.75]; +float[] spdAimedBubble = [12, 14, 16]; + +int[] delayAimed = [11, 9, 7]; +float[] accelAimed = [6/60, 8/50, 10/40]; +float[] maxspdAimed = [7, 8, 9]; + +int[] delayBeforeAim = [40, 30, 20]; +int[] delayFinalBurst = [45, 35, 30]; +int[] thresholdStopSpin = [80, 70, 60]; + +// Includes ahoy + +#include "script/KevinSystem/Universal_Lib.txt" // The library to include all libraries :sans: :nail_care: + +@Initialize { + + //SetIntersectionVisualization(true); + + SetAutoDeleteObject(true); + + _InitDifficulty(difficultySelect); + + //difficultySelect = 1; // debug + + SetShotAutoDeleteClip(64, 64, 64, 64); + + 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, GetCommonData("Boss Position X", STG_WIDTH/2), GetCommonData("Boss Position Y", STG_HEIGHT/2)); + ObjEnemy_SetMaximumDamage(bossObj, 999); + + // PLACEHOLDER! + let imgExRumia = GetModuleDirectory() ~ "script/ExRumia/ExRumia.png"; + ObjPrim_SetTexture(bossObj, imgExRumia); + ObjSprite2D_SetSourceRect(bossObj, 64, 1, 127, 64); + ObjSprite2D_SetDestCenter(bossObj); + ObjRender_SetScaleXYZ(bossObj, 2, 2, 1); + ObjRender_SetColor(bossObj, 0xB93C3C); + ObjMove_SetDestAtFrame(bossObj, STG_WIDTH/2, 550, 1); + // PLACEHOLDER! + + /*_SoloCutin( + "script/invalid.png", + 0, 0, 1, 1, + bossObj, objScene, "\"Euphoric Blooming of a New Market\"", + 40, 4, 0x2868B9, 0x1D115D, + 10, STG_HEIGHT*1/10-30, 41 + );*/ + + //WriteLog(spellPIV); + WriteLog(ObjEnemyBossScene_GetInfo(objScene, INFO_SPELL_SCORE)); + + mainTask(); + _FadeInvincibility(bossObj, 150, 150, 1); + endingnew(); +} + +@Event { + + alternative(GetEventType()) + + case(EV_REQUEST_LIFE) { + SetScriptResult(3000); + } + + case(EV_REQUEST_TIMER) { + SetScriptResult(25); + } + +} + +@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), 100); + + yield; + +} + +@Finalize { + +} + +/* + +Red rain bullets start falling from above in an oscillating/sine wave pattern. Remilia herself fires rainbow bullet bursts that are gravity-manipulated (see Chimata’s first or third spell in my Pride Jam script) + +Parameters: + +// Red Rain + +- Number of rain spawners +- Start x +- End x +- Angle offset value for oscillation +- Delay between bullet spawns +- Bullet acceleration +- Bullet maxspeed + +// Rainbow Burst (see Meiling's Colorful Light Chaos Dance) -> how the hell do I do this????? + +- Spiral density +- Number of spiral "arms" +- y speed acceleration +- max y speed + +*/ + +task mainTask { + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE) > 0){ + + yield; + + } + +} + +task endingnew(){ + + while(ObjEnemy_GetInfo(bossObj, INFO_LIFE)>0){ + yield; + } + + _GoToBrazil(objScene, bossObj, 12, 24); + wait(120); + ObjSound_SetVolumeRate(fire2, 20); + + CloseScript(GetOwnScriptID); + +} + + diff --git a/script/game/replay/Non1_replay01.dat b/script/game/replay/Non1_replay01.dat new file mode 100644 index 0000000..293c621 Binary files /dev/null and b/script/game/replay/Non1_replay01.dat differ diff --git a/script/game/replay/Non1_replay02.dat b/script/game/replay/Non1_replay02.dat new file mode 100644 index 0000000..551a29f Binary files /dev/null and b/script/game/replay/Non1_replay02.dat differ diff --git a/script/game/replay/Non2_replay01.dat b/script/game/replay/Non2_replay01.dat new file mode 100644 index 0000000..60c0428 Binary files /dev/null and b/script/game/replay/Non2_replay01.dat differ diff --git a/script/game/replay/Non2_replay02.dat b/script/game/replay/Non2_replay02.dat new file mode 100644 index 0000000..5c9e6f9 Binary files /dev/null and b/script/game/replay/Non2_replay02.dat differ diff --git a/script/game/replay/Spell3_replay01.dat b/script/game/replay/Spell3_replay01.dat new file mode 100644 index 0000000..9013aaa Binary files /dev/null and b/script/game/replay/Spell3_replay01.dat differ diff --git a/script/game/replay/Spell3_replay02.dat b/script/game/replay/Spell3_replay02.dat new file mode 100644 index 0000000..583ca97 Binary files /dev/null and b/script/game/replay/Spell3_replay02.dat differ diff --git a/script/game/resourceLib/Spritesheet_StationJam.png b/script/game/resourceLib/Spritesheet_StationJam.png new file mode 100644 index 0000000..d55d696 Binary files /dev/null and b/script/game/resourceLib/Spritesheet_StationJam.png differ diff --git a/script/player/Chimata/Chimata_Function.dnh b/script/player/Chimata/Chimata_Function.dnh new file mode 100644 index 0000000..7aeb7b9 --- /dev/null +++ b/script/player/Chimata/Chimata_Function.dnh @@ -0,0 +1,115 @@ + +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(inferno);} + 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; + } + +} \ 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..6edd669 --- /dev/null +++ b/script/player/Chimata/Chimata_Main.dnh @@ -0,0 +1,736 @@ +#TouhouDanmakufu[Player] +#ScriptVersion[3] +#ID["Chimata"] +#Title["Chimata Tenkyuu"] +#Text["Shot Type: Blank Card Set[r]Spell Card: Shield of Market Regulation"] + +//#Image["./mariremi_lib/mariremi_illust.png"] + +#ReplayName["Chimata"] + +#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" + +let csd = GetCurrentScriptDirectory(); + +// Global Variables + +float maxX = GetStgFrameWidth(); +float maxY = GetStgFrameHeight(); + +// Images & Sound + +let teamimg = csd ~ "./playerlib/Chimata_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; + +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 + +float[] PlayerSpd = [10, 5.35]; + +// 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); + } + 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); + + _HitboxRender(ripplayer, objPlayer, teamimg, teamimg, 1280, 512, 1408, 640, 1536, 896, 2048, 1408, 0.3, 0.65); + SetShotAutoDeleteClip(256, 256, 256, 256); + + // Shot functions + + //_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){ + 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); + //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(); + _SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, GetPlayerInvincibilityFrame()); + } + + else { + SetScriptResult(false); + } + } + + case(EV_HIT){ + ObjSound_Play(predeathsfx); + _DeathbombWarning(teamimg, [1536, 384, 1536+512, 384+512], 15, 0.75); + } + + case(EV_PLAYER_SHOOTDOWN){ + ObjSound_Play(deathsfx); + ripplayer = true; + _SigilCall(true, teamimg, 768, 512, 768+256, 768, objPlayer, 120); + } + + case(EV_PLAYER_REBIRTH){ + ripplayer = false; + SetPlayerInvincibilityFrame(180); + _SigilCall(false, teamimg, 768+256, 512, 768+512, 768, objPlayer, 150); + SetPlayerSpell( max(2,GetPlayerSpell()) ); + } + + case(EV_GRAZE){ + grazecounter += GetEventArgument(0); + ObjSound_Play(grazesfx); + while(grazecounter >= 10){ + SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue")+10); + grazecounter -= 10; + } + } +} + +@Finalize{ + +} + +// Homing + +task _HomeShot(int option_) { + + int shot_ = 0; + + float duration = 1; + float durationOption = 99999; + + bool homingBool = false; + + float basepenetrate = ObjShot_GetPenetration(shot_); + float basedmg = ObjShot_GetDamage(shot_); + + // + + for (int t = 0i; t < durationOption && !Obj_IsDeleted(option_); 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(objPlayer), enemyY - ObjMove_GetY(objPlayer)); + + // 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 < durationOption && !Obj_IsDeleted(option_) && !Obj_IsDeleted(targetID) && ObjEnemy_GetInfo(targetID, INFO_LIFE) != 0 && GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE; t++) { + + ObjShot_SetAutoDelete(option_, false); + + float shotAngle = NormalizeAngle(ObjMove_GetAngle(option_)); // Angle of the player shot + float targetAngle = NormalizeAngle(atan2(ObjMove_GetY(targetID) - ObjMove_GetY(option_), ObjMove_GetX(targetID) - ObjMove_GetX(option_))); // 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.75, min(15, f) / 15); + // Homing speed? + ObjMove_SetAngle(option_, Interpolate_Decelerate(shotAngle, shotAngle + angleDistance, homeRate)); // Interpolate_Necko + f++; + yield; + } + } + + /*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.75, min(60, f) / 60); + // Homing speed? + ObjMove_SetAngle(shot_, Interpolate_Accelerate(shotAngle, shotAngle + angleDistance, 1)); // Interpolate_Necko + f++; + yield; + } + ObjShot_SetAutoDelete(shot_, true); + ObjMove_SetAngularVelocity(shot_, 0); + homingBool = false; + }*/ + } + + yield; + } +} + +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(){ + + // Offsets for 4 front options + + // Alternative player option function + + 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 + ){ + // IMPORTANT! + let option = ObjShot_Create(OBJ_SHOT); + ObjShot_Regist(option); + ObjShot_SetAutoDelete(option, false); + ObjShot_SetGraphic(option, 3); + ObjShot_SetPenetration(option, 9999^9999); + ObjShot_SetDamage(option, 0); + ObjShot_SetIntersectionEnable(option, false); + ObjMove_SetAngle(option, 270); + // + + bool visible; + int animate = 0; + float optx; + float opty; + + ObjRender_SetScaleXYZ(option, scale); + ObjRender_SetBlendType(option, BLEND_ALPHA); + ObjRender_SetAlpha(option, 225); + 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){ + ObjMove_SetPosition(option, GetPlayerX()+offsetx, GetPlayerY()+offsety); + 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; + + } + + float offsetX1 = 125; + float offsetX2 = offsetX1 * 2; + float offsetY1 = 75; + + // Array that contains static/unchanging values for the PlayerOption + + let val = [0, 512, 256, 768, 0.3, 256, 1, 1, false, false, 0, true, true]; + + // Option handling (right -> rightmost -> left -> leftmost) + + float[][] offsetArray = [[offsetX1, offsetY1], [offsetX2, 0], [-offsetX1, offsetY1], [-offsetX2, 0]]; + + int opt1 = PlayerOption( + offsetArray[0][0], offsetArray[0][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int opt2 = PlayerOption( + offsetArray[1][0], offsetArray[1][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int opt3 = PlayerOption( + offsetArray[2][0], offsetArray[2][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int opt4 = PlayerOption( + offsetArray[3][0], offsetArray[3][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int[] optArray = [opt1, opt2, opt3, opt4]; + + _HomingStars(optArray[0], 0); _HomeShot(optArray[0]); + _HomingStars(optArray[1], 1); _HomeShot(optArray[1]); + _HomingStars(optArray[2], 2); _HomeShot(optArray[2]); + _HomingStars(optArray[3], 3); _HomeShot(optArray[3]); + + task _HomingStars(option, value){ + + loop{ + + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + + async{ + + if(value == 0){ + + ascent(i in 0..15){ + ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX+offsetX1, i/15)); + ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY+offsetY1, i/15)); + yield; + } + + } + + else if(value == 1){ + + ascent(i in 0..15){ + ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX+offsetX1*2, i/15)); + ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY, i/15)); + yield; + } + + } + + else if(value == 2){ + + ascent(i in 0..15){ + ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX-offsetX1, i/15)); + ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY+offsetY1, i/15)); + yield; + } + + } + + else if(value == 3){ + + ascent(i in 0..15){ + ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX-offsetX1*2, i/15)); + ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY, i/15)); + yield; + } + + } + + } + + async{ + if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && IsPermitPlayerShot && !ripplayer){ + + if(shotspeed % 5 == 0){ + float x = ObjRender_GetX(option); + float y = ObjRender_GetY(option); + + ascent(i in -1..1){ + let shotA = CreatePlayerShotA1(-50+x+25-50*i, y, 50, ObjMove_GetAngle(option), 2, 1.1, 2); + _BulletRescalePlayer(shotA, 0.7, true, 1); + ObjRender_SetAlpha(shotA, 255*(universalAlpha/100)); + Obj_SetRenderPriorityI(shotA, 39); + ObjSound_Play(basesfx); + + } + } + } + } + + } + + else{ + + async{ + + if(value == 0){ + + ascent(i in 0..15){ + ObjMove_SetAngle(option, Interpolate_Decelerate(ObjMove_GetAngle(option), 275, i/15)); + ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX+offsetX1*0.45, i/15)); + ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY+offsetY1, i/15)); + yield; + } + + } + + else if(value == 1){ + + ascent(i in 0..15){ + ObjMove_SetAngle(option, Interpolate_Decelerate(ObjMove_GetAngle(option), 295, i/15)); + ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX+offsetX1*0.75, i/15)); + ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY, i/15)); + yield; + } + + } + + else if(value == 2){ + + ascent(i in 0..15){ + ObjMove_SetAngle(option, Interpolate_Decelerate(ObjMove_GetAngle(option), 265, i/15)); + ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX-offsetX1*0.45, i/15)); + ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY+offsetY1, i/15)); + yield; + } + + } + + else if(value == 3){ + + ascent(i in 0..15){ + ObjMove_SetAngle(option, Interpolate_Decelerate(ObjMove_GetAngle(option), 245, i/15)); + ObjMove_SetX(option, Interpolate_Decelerate(ObjMove_GetX(option), playerX-offsetX1*0.75, i/15)); + ObjMove_SetY(option, Interpolate_Decelerate(ObjMove_GetY(option), playerY, i/15)); + yield; + } + + } + + } + + async{ + if(GetVirtualKeyState(VK_SHOT) != KEY_FREE && IsPermitPlayerShot && !ripplayer){ + + if(shotspeed % 5 == 0){ + float x = ObjRender_GetX(option); + float y = ObjRender_GetY(option); + + ascent(i in -1..1){ + let shotA = CreatePlayerShotA1(-50+x+25-50*i, y, 50, ObjMove_GetAngle(option), 2.6, 1.1, 1); + _BulletRescalePlayer(shotA, 0.7, true, 1); + ObjRender_SetAlpha(shotA, 255*(universalAlpha/100)); + Obj_SetRenderPriorityI(shotA, 39); + ObjSound_Play(basesfx); + + } + } + } + } + + } + + + yield; + } + + } + +} + +// Basic player parameters + +task parameterrender(){ + + SetPlayerItemScope(120); + SetPlayerLife(9); // Debug + SetPlayerSpell(2); + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); // (original: 5.25/2.0) + SetPlayerRebirthFrame(12); + SetPlayerAutoItemCollectLine(GetStgFrameHeight/3); + SetPlayerRebirthLossFrame(0); + ObjPlayer_AddIntersectionCircleA1(objPlayer, 0, 0, 1.25, 40); + +} + +// Renders the shottype +// Player sprites + +task playerrender(){ + + // Why is this movement code so cursed jesus fucking christ + + float scale = 0.32; // Scalies + int frame = 0; + + ObjPrim_SetTexture(objPlayer, teamimg); + ObjSprite2D_SetSourceRect(objPlayer, 0, 0, 400, 400); + ObjSprite2D_SetDestCenter(objPlayer); + Obj_SetRenderPriorityI(objPlayer, 42); + 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, 400, 400, scale, 4, 6); + if (frame >= (5*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 + SetForbidPlayerShot(true); + SetForbidPlayerSpell(true); + SetPlayerInvincibilityFrame(32*3+32*3+42*3+120+45); + // Spell object + let manageObj = GetSpellManageObject(); // SPELL BEGINS + ObjSpell_Regist(manageObj); + ObjSound_Play(bombsfx); + SetPlayerSpeed(PlayerSpd[0]*1.5, PlayerSpd[0]*1.5); + + int hakkero = CreatePlayerShotA1(playerX, playerY, 0, 0, 12, 999999, 4); + ObjShot_SetIntersectionEnable(hakkero, true); + ObjShot_SetEraseShot(hakkero, true); + ObjShot_SetSpellFactor(hakkero, true); + + async{ + ascent(i in 0..45){ + _BulletRescalePlayer(hakkero, Interpolate_Decelerate(0.1, 1, i/45), true, 1); + ObjRender_SetAlpha(hakkero, Interpolate_Decelerate(0, 255, i/45)); + yield; + } + } + + ascent(i in 0..240){ + ObjMove_SetPosition(hakkero, playerX, playerY); + yield; + } + + // Cleanup, end of spell + ObjShot_FadeDelete(hakkero); + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); + SetForbidPlayerShot(false); + wait(60); + SetForbidPlayerSpell(false); + Obj_Delete(manageObj); // !!! IMPORTANT !!! + +} + +// Screenshake function for bomb's duration - adapted from Sparen's tutorials + +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; +} + diff --git a/script/player/Chimata/Chimata_ShotConst.dnh b/script/player/Chimata/Chimata_ShotConst.dnh new file mode 100644 index 0000000..b3dd32f --- /dev/null +++ b/script/player/Chimata/Chimata_ShotConst.dnh @@ -0,0 +1,12 @@ +let current = GetCurrentScriptDirectory(); +let path = current ~ "Chimata_ShotData.dnh"; +LoadPlayerShotData(path); +// ----- + +const HOMING_STAR = 1; +const ELECTRIC_FIRE = 2; +const BASE = 3; +const ELECTRIC_FIRE_ALT = 5; +const LOCKON_KNIFE = 6; + + diff --git a/script/player/Chimata/Chimata_ShotData.dnh b/script/player/Chimata/Chimata_ShotData.dnh new file mode 100644 index 0000000..79b828e --- /dev/null +++ b/script/player/Chimata/Chimata_ShotData.dnh @@ -0,0 +1,48 @@ +shot_image = "./playerlib/Chimata_Sheet.png" + +ShotData{ + id = 0 // Dummy + rect = (0,0,0,0) + render = ALPHA + alpha = 0 + collision = 32 +} + +// Money + +ShotData{ + id = 1 + rect = (256, 512, 512, 896) + render = ALPHA + alpha = 255 + collision = (128, 0, 74) // Hitbox of arrows is not centered on the sprite +} + +// Knìfe + +ShotData{ + id = 2 + rect = (512, 512, 768, 896) + render = ALPHA + alpha = 200 + collision = (128, 0, 74) // Hitbox of arrows is not centered on the sprite +} + +ShotData{ + id = 3 + rect = (0, 512, 256, 768) + render = ALPHA + alpha = 255 + collision = (128, 0, 74) // Hitbox of arrows is not centered on the sprite +} + +// Bomb + +ShotData{ + id = 4 + rect = (0, 896, 512, 1408) + render = ADD_ARGB + angular_velocity = 5; + alpha = 255 + collision = 160 +} \ 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..eca20b1 Binary files /dev/null and b/script/player/Chimata/playerlib/Chimata_Sheet.png 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/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/Jam8_Rinnosuke/Default_Player_MagicCircle.png b/script/player/Jam8_Rinnosuke/Default_Player_MagicCircle.png new file mode 100644 index 0000000..0e0d6a1 Binary files /dev/null and b/script/player/Jam8_Rinnosuke/Default_Player_MagicCircle.png differ diff --git a/script/player/Jam8_Rinnosuke/Rinnosuke_Main.dnh b/script/player/Jam8_Rinnosuke/Rinnosuke_Main.dnh new file mode 100644 index 0000000..698b06a --- /dev/null +++ b/script/player/Jam8_Rinnosuke/Rinnosuke_Main.dnh @@ -0,0 +1,452 @@ +#TouhouDanmakufu[Player] +#ScriptVersion[3] +#ID["Rinno"] +#Title["Rinnosuke"] +#Text["Unfocused Shot: Rage of the Electronic[r]Focused Shot: Doomsday Button[r]Spell Card: Prototype \"Volatile Hakkero\""] +//#Image["./kevkou_lib/gayimg.png"] + +#ReplayName["Rinno"] + +#include "script/KevinSystem/Kevin_PlayerLib.txt" +#include "./Rinnosuke_ShotConst.dnh" +#include "./soundlib.txt" + +#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(); + +int targetedenemy = 0; // This will be used to store the enemy ID Kouda's homing shots aim at + +// Images & Sound + +let teamimg = "script/TouhouJam8_SRE/Jam8_Resource/jam8Sprite.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; + +int[] _enemyArray = []; // Prepare an array to store enemy IDs for Kouda's homing shot +int[] _existArray = []; + +int grazecounter = 0; // For basic graze = PIV mechanic + +// 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); + } + else{} + + // Stuff + parameterrender(); + playerrender(); + plrender = Obj_GetRenderPriorityI(objPlayer); + + _SoundTask(); + + _Mechanic(ripplayer, _enemyArray, _existArray, GetStgFrameWidth(), GetStgFrameHeight(), objPlayer, GetEnemyBossSceneObjectID(), 3, 2, 30); + + _HitboxRender(ripplayer, objPlayer, teamimg, teamimg, 512, 0, 640, 128, 768, 0, 1024, 256, 0.2, 1); + + // Shot functions + + //_EnemySelect(); + + _Homing(); + //_UnfocusedShot(); + + //_ShotType(); + + // Shot data loading + LoadPlayerShotData(csd ~ "./Rinnosuke_ShotData.dnh"); +} + +@MainLoop{ + _enemyArray = GetIntersectionRegistedEnemyID; // Constantly update the enemy ID array + shotspeed += 1; // Managing the shot rate + playerX = ObjMove_GetX(objPlayer); + playerY = ObjMove_GetY(objPlayer); + yield; +} + +@Event{ + alternative(GetEventType) + + // PIV-item spawning events + + case(EV_DELETE_SHOT_PLAYER){ + let graphic = GetEventArgument(2); + float[] position = GetEventArgument(1); + let obj = CreatePlayerShotA1(position[0], position[1], 0, 0, 0, 99999, graphic); + ObjShot_SetIntersectionEnable(obj, false); + _DeleteEffect(obj); + } + + 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(); + _SigilCall(false, teamimg, 256, 512, 512, 768, objPlayer, GetPlayerInvincibilityFrame()); + } + else { + SetScriptResult(false); + } + } + + case(EV_HIT){ + //_DeathbombWarning(teamimg, [2560, 512, 2560+512, 1024], 30, 0.65); + ObjSound_Play(predeathsfx); + } + + case(EV_PLAYER_SHOOTDOWN){ + ObjSound_Play(deathsfx); + ripplayer = true; + _SigilCall(true, teamimg, 0, 512, 256, 768, objPlayer, 120); + } + + case(EV_PLAYER_REBIRTH){ + ripplayer = false; + SetPlayerInvincibilityFrame(180); + _SigilCall(false, teamimg, 256, 512, 512, 768, objPlayer, GetPlayerInvincibilityFrame()); + SetPlayerSpell( max(3, GetPlayerSpell()) ); + } + + case(EV_GRAZE){ + grazecounter += GetEventArgument(0); + while(grazecounter >= 10){ + SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue")+10); + grazecounter -= 10; + } + } +} + +@Finalize{ + +} + +task _DeleteEffect(obj){ + ObjRender_SetBlendType(obj, BLEND_ADD_ARGB); + ascent(i in 0..30){ + ObjRender_SetAlpha(obj, Interpolate_Decelerate(120, 0, i/30)); + ObjRender_SetScaleXYZ(obj, Interpolate_Decelerate(0.5, 2, i/30)); + yield; + } + Obj_Delete(obj); +} +// Basic player parameters + +task parameterrender(){ + SetPlayerItemScope(200); // Special Ability 1 + SetPlayerLife(5); // Debug + SetPlayerSpell(3); + SetPlayerSpeed(6.5, 2.8); // (original: 4.5/1.75) + SetPlayerRebirthFrame(30); // Special Ability 2 + SetPlayerAutoItemCollectLine(GetStgFrameHeight/3); //596x632 STG frame + SetPlayerRebirthLossFrame(0); + ObjPlayer_AddIntersectionCircleA1(objPlayer,0,0,1.5,25); +} + +// Renders the shottype + +// Selects an enemy to home on. + +task _HomeShot(int shot_) { + + float duration = 55; + bool homingBool = false; + float basepenetrate = ObjShot_GetPenetration(shot_); + float basedmg = ObjShot_GetDamage(shot_); + + // Original code + + async{ + _BulletRescalePlayer(shot_, 0.75, true, 1.1); + } + + // + + 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(objPlayer), enemyY - ObjMove_GetY(objPlayer)); + + // 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.75, min(60, f) / 60); + // 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 _Homing(){ + + let optionA = PlayerOption(50, 0, 256, 256, 512, 512); + let optionB = PlayerOption(-50, 0, 256, 256, 512, 512); + let optionC = PlayerOption(90, 30, 256, 256, 512, 512); + let optionD = PlayerOption(-90, 30, 256, 256, 512, 512); + + int shotspeedhome = 0; + + int[] optionList = [optionA, optionB, optionC, optionD]; + int[] optionList1 = [optionA, optionC]; + int[] optionList2 = [optionB, optionD]; + + int a = 0; + + loop{ + if(shotspeedhome % 5 == 0 && GetVirtualKeyState(VK_SHOT) != KEY_FREE && IsPermitPlayerShot && !ripplayer){ + + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + + for each (int option in ref optionList){ + //"l + float x = ObjRender_GetX(option); + float y = ObjRender_GetY(option); + + let shotA = CreatePlayerShotA1(x, y, 15, 270, 2.65, 2, FOCUSED); + //ObjMove_AddPatternA2(shotA, 1, 5, NO_CHANGE, -0.1, 3.75, rand(-0.4, 0.4)); + + _HomeShot(shotA); + } + + ascent(i in -2..3){ + int shot = CreatePlayerShotA1(playerX, playerY, 17, 270-5*i, 3.5, 2, UNFOCUSED); + _BulletRescalePlayer(shot, 0.5, true, 1); + } + + } + + else{ + + for each (int option in ref optionList1){ + //" + float x = ObjRender_GetX(option); + float y = ObjRender_GetY(option); + + ascent(i in -1..2){ + int shot = CreatePlayerShotA1(x, y, 17, 240-10*i, 4, 1.75, UNFOCUSED); + _BulletRescalePlayer(shot, 0.5, true, 1); + } + + } + + for each (int option in ref optionList2){ + //" + float x = ObjRender_GetX(option); + float y = ObjRender_GetY(option); + + ascent(i in -1..2){ + int shot = CreatePlayerShotA1(x, y, 17, 300+10*i, 4, 1.75, UNFOCUSED); + _BulletRescalePlayer(shot, 0.5, true, 1); + } + + } + + } + } + shotspeedhome++; + yield; + } +} + +// Player option rendering + +function PlayerOption(offsetx, offsety, left, top, right, bottom){ + let option = ObjPrim_Create(OBJ_SPRITE_2D); + bool visible; + int animate = 0; + float optx; + float opty; + + ObjPrim_SetTexture(option, teamimg); + ObjSprite2D_SetSourceRect(option, left, top, right, bottom); + ObjSprite2D_SetDestCenter(option); + ObjRender_SetScaleXYZ(option, 0.25, 0.25, 1); + ObjRender_SetBlendType(option, BLEND_ALPHA); + ObjRender_SetAlpha(option, 180); + Obj_SetRenderPriorityI(option, 41); + ObjRender_SetPosition(option, offsetx, offsety, 1); + + async{ + loop{ + ObjRender_SetPosition(option, GetPlayerX()+offsetx, GetPlayerY()+offsety, 1); + yield; + } + } + + async{ + loop{ + if(ripplayer){Obj_SetVisible(option, false); visible = false;} + else {Obj_SetVisible(option, true); visible = true;} + yield; + } + } + + return option; +} + +// Player sprites + +task playerrender(){ + + // Why is this movement code so cursed jesus fucking christ + + float scale = 0.4; // Scalies + + ObjPrim_SetTexture(objPlayer, teamimg); + ObjSprite2D_SetSourceRect(objPlayer, 0, 256, 256, 512); + ObjSprite2D_SetDestCenter(objPlayer); + Obj_SetRenderPriorityI(objPlayer, 42); + ObjRender_SetScaleXYZ(objPlayer, scale, scale, 1); + +} + +task Bomb(){ + // Preparation + //SetForbidPlayerShot(true); + SetForbidPlayerSpell(true); + SetPlayerInvincibilityFrame(300); + // Spell object + let manageObj = GetSpellManageObject(); // SPELL BEGINS + ObjSpell_Regist(manageObj); + ObjSound_Play(bombsfx); + + // Spell + + int hakkero = CreatePlayerShotA1(playerX, playerY, 0, 0, 12, 999999, BOMB); + ObjShot_SetIntersectionEnable(hakkero, true); + ObjShot_SetEraseShot(hakkero, true); + ObjShot_SetSpellFactor(hakkero, true); + + async{ + ascent(i in 0..45){ + _BulletRescalePlayer(hakkero, Interpolate_Decelerate(0.5, 2.25, i/45), true, 1); + ObjRender_SetAlpha(hakkero, Interpolate_Decelerate(0, 255, i/45)); + yield; + } + } + + ascent(i in 0..240){ + yield; + } + + // Cleanup, end of spell + ObjShot_FadeDelete(hakkero); + SetForbidPlayerShot(false); + wait(60); + SetForbidPlayerSpell(false); + Obj_Delete(manageObj); // !!! IMPORTANT !!! + +} + +// Screenshake function for bomb's duration - adapted from Sparen's tutorials + +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; +} diff --git a/script/player/Jam8_Rinnosuke/Rinnosuke_ShotConst.dnh b/script/player/Jam8_Rinnosuke/Rinnosuke_ShotConst.dnh new file mode 100644 index 0000000..5e19cba --- /dev/null +++ b/script/player/Jam8_Rinnosuke/Rinnosuke_ShotConst.dnh @@ -0,0 +1,7 @@ +let current = GetCurrentScriptDirectory(); +let path = current ~ "Rinnosuke_ShotData.dnh"; +LoadPlayerShotData(path); +// ----- +const FOCUSED = 1; +const UNFOCUSED = 2; +const BOMB = 3; \ No newline at end of file diff --git a/script/player/Jam8_Rinnosuke/Rinnosuke_ShotData.dnh b/script/player/Jam8_Rinnosuke/Rinnosuke_ShotData.dnh new file mode 100644 index 0000000..3f19fc9 --- /dev/null +++ b/script/player/Jam8_Rinnosuke/Rinnosuke_ShotData.dnh @@ -0,0 +1,14 @@ +shot_image = "./../../TouhouJam8_SRE/Jam8_Resource/jam8Sprite.png" + +ShotData{ + id = 0 // Dummy + rect = (0,0,0,0) + render = ALPHA + alpha = 0 + collision = 12 +} + +// Rinnosuke's shots +ShotData{id = 1 rect = (512, 256, 639, 383) render = ALPHA alpha = 180 collision = 38 fixed_angle = false angular_velocity = 3} // Homing shot, spins +ShotData{id = 2 rect = (640, 256, 768, 384) render = ALPHA alpha = 150 collision = 38} // Unfocused shot +ShotData{id = 3 rect = (768, 256, 1023, 511) render = ADD_ARGB alpha = 255 collision = 115 fixed_angle = false angular_velocity = 8} // Bomb \ No newline at end of file diff --git a/script/player/Jam8_Rinnosuke/sound/bfxr_PlayerDie.wav b/script/player/Jam8_Rinnosuke/sound/bfxr_PlayerDie.wav new file mode 100644 index 0000000..b77623d Binary files /dev/null and b/script/player/Jam8_Rinnosuke/sound/bfxr_PlayerDie.wav differ diff --git a/script/player/Jam8_Rinnosuke/sound/bfxr_PreDeath.wav b/script/player/Jam8_Rinnosuke/sound/bfxr_PreDeath.wav new file mode 100644 index 0000000..e05e61e Binary files /dev/null and b/script/player/Jam8_Rinnosuke/sound/bfxr_PreDeath.wav differ diff --git a/script/player/Jam8_Rinnosuke/sound/bfxr_RinnoBomb.wav b/script/player/Jam8_Rinnosuke/sound/bfxr_RinnoBomb.wav new file mode 100644 index 0000000..00d3b5b Binary files /dev/null and b/script/player/Jam8_Rinnosuke/sound/bfxr_RinnoBomb.wav differ diff --git a/script/player/Jam8_Rinnosuke/soundlib.txt b/script/player/Jam8_Rinnosuke/soundlib.txt new file mode 100644 index 0000000..068ecc3 --- /dev/null +++ b/script/player/Jam8_Rinnosuke/soundlib.txt @@ -0,0 +1,25 @@ + +let sddir = GetCurrentScriptDirectory() ~ "./sound"; + +function LoadEx(targetobj, targetpath, targetvol){ + + ObjSound_Load(targetobj, targetpath); + ObjSound_SetVolumeRate(targetobj, targetvol); + +} + +// Universal sounds + +let bomb = sddir ~ "./bfxr_RinnoBomb.wav"; +let ded = sddir ~ "./bfxr_PlayerDie.wav"; +let hit = sddir ~ "./bfxr_PreDeath.wav"; + +let bombsfx = ObjSound_Create(); +let deathsfx = ObjSound_Create(); +let predeathsfx = ObjSound_Create(); + +task _SoundTask(){ + LoadEx(bombsfx, bomb, 15); + LoadEx(deathsfx, ded, 40); + LoadEx(predeathsfx, hit, 55); +} \ No newline at end of file diff --git a/script/player/PrideJam_ByakMiko/ByakMiko_Function.dnh b/script/player/PrideJam_ByakMiko/ByakMiko_Function.dnh new file mode 100644 index 0000000..6df30b9 --- /dev/null +++ b/script/player/PrideJam_ByakMiko/ByakMiko_Function.dnh @@ -0,0 +1,218 @@ + +// Particle list for laser effect + +int LaserEffect = ObjParticleList_Create(OBJ_PARTICLE_LIST_2D); +int[] rect = [2816, 0, 2816+256, 0+256]; + +ObjPrim_SetTexture(LaserEffect, "script/player/PrideJam_ByakMiko/playerlib/ByakMiko_Sheet.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(0.5, 0.2, 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); + + 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{ + 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){ /* */ + + 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, 38); + _Follow(laser, target); + + _LaserSpriteRender( + teamimg, laser, ang, + 3072, 0, 3072+256, 256, + 0.45, 20, 38, 255*(universalAlpha/100), + 0.14 + ); + + // 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 && GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE && !ripplayer && IsPermitPlayerShot){ + + if(shotspeed % 5 == 0){ + ObjSound_Play(inferno); + } + + 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(9, 11)); + } + } + + // 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/PrideJam_ByakMiko/ByakMiko_Function.txt b/script/player/PrideJam_ByakMiko/ByakMiko_Function.txt new file mode 100644 index 0000000..e54e069 --- /dev/null +++ b/script/player/PrideJam_ByakMiko/ByakMiko_Function.txt @@ -0,0 +1,246 @@ + +// Particle list for laser effect + +int LaserEffect = ObjParticleList_Create(OBJ_PARTICLE_LIST_2D); +int[] rect = [2816, 0, 2816+256, 0+256]; + +ObjPrim_SetTexture(LaserEffect, "script/player/PrideJam_ByakMiko/playerlib/ByakMiko_Sheet.png"); + +Obj_SetRenderPriorityI(LaserEffect, 39); +ObjPrim_SetPrimitiveType(LaserEffect, PRIMITIVE_TRIANGLELIST); +ObjPrim_SetVertexCount(LaserEffect, 4); + +ObjRender_SetBlendType(LaserEffect, BLEND_ALPHA); + +// 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(0.5, 0.2, 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); + + 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{ + 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){ /* */ + + 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, 38); + _Follow(laser, target); + + _LaserSpriteRender( + teamimg, laser, ang, + 3072, 0, 3072+256, 256, + 0.45, 20, 38, 200, + 0.14 + ); + + // 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 && GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE && !ripplayer && IsPermitPlayerShot){ + + if(shotspeed % 5 == 0){ + ObjSound_Play(inferno); + } + + 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){ + + int[] ResortList = []; + + // Debugging: gets distance from player to the laser, appends it into an array + + task Resort(){ + for each(int enm in EnemyList){ + ResortList = append(ResortList, GetObjectDistance(enm, target)); + } + WriteLog(ResortList); + ResortList = []; + } + + async{ + loop{ + EnemyList = ObjCol_GetListOfIntersectedEnemyID(target); + yield; + } + } + + async{ + loop{ + Resort(); + wait(60); + } + } + + // 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(9, 11)); + } + } + + // Damage effects + async{ + loop{ + ascent(i in -1..length(EnemyList)-1){ + float dmgCalc = max(1, basedmg - (basedmg * 0.2 * i)); + ObjEnemy_SetLife(EnemyList[i], ObjEnemy_GetInfo(EnemyList[i], INFO_LIFE) - dmgCalc); + } + yield; + } + } + +} +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/PrideJam_ByakMiko/ByakMiko_Main.dnh b/script/player/PrideJam_ByakMiko/ByakMiko_Main.dnh new file mode 100644 index 0000000..db5b8fa --- /dev/null +++ b/script/player/PrideJam_ByakMiko/ByakMiko_Main.dnh @@ -0,0 +1,575 @@ +#TouhouDanmakufu[Player] +#ScriptVersion[3] +#ID["ByakMiko"] +#Title["Byakuren Hijiri & Toyosatomimi no Miko"] +#Text["Unfocused Shot: Indra's Sorcery Buzzsaws[r]An elegant spread of thunder needles.[r][r]Focused Shot: Four Shining Articles[r]A crossing of high-power divine lasers.[r][r]Special Ability: Smaller hitbox."] + +//#Image["./marimiko_lib/marimiko_illust.png"] + +#ReplayName["ByakMiko"] + +#include "script/KevinSystem/Kevin_PlayerLib.txt" +#include "script/KevinSystem/PlayerSoundLib.dnh" + +#include "./ByakMiko_Function.dnh" +#include "./ByakMiko_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/ByakMiko_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); + +int frameidlebyak = 0; +int frameidlemiko = 0; +int framemovebyak = 0; +int framemovemiko = 0; + +bool ripplayer = false; +float shotspeed = 0; +float bombrand = 0; + +bool bombenable = false; +bool focusactive = false; +bool ishoming = 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 + +float[] PlayerSpd = [11.5, 5.8]; + +// 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); + } + 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); + + _HitboxRender(ripplayer, objPlayer, teamimg, teamimg, 2560, 512, 2688, 640, 2816, 1024, 2816+511, 1024+511, 0.22, 0.65); + SetShotAutoDeleteClip(256, 256, 256, 256); + + // Shot functions + + //_CAVELaser(); + ByakShot(); + _MikoOption(); + + // Shot data loading + LoadPlayerShotData(csd ~ "./ByakMiko_ShotData.dnh"); +} + +@MainLoop{ + 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){ + 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); + } + + // 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); + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){_FocusBomb(); _SigilCall(false, teamimg, 2816+256, 512, 2816+512, 768, objPlayer, GetPlayerInvincibilityFrame());} + else{_UnfocusBomb(); + _SigilCall(false, teamimg, 2816+256, 512, 2816+512, 768, objPlayer, GetPlayerInvincibilityFrame()); + } + } + + else { + SetScriptResult(false); + } + } + + case(EV_HIT){ + ObjSound_Play(predeathsfx); + _DeathbombWarning(teamimg, [1792, 512, 1792+512, 512+512], 15, 0.75); + } + + case(EV_PLAYER_SHOOTDOWN){ + ObjSound_Play(deathsfx); + ripplayer = true; + _SigilCall(true, teamimg, 2816, 512, 2816+256, 768, objPlayer, 120); + } + + case(EV_PLAYER_REBIRTH){ + ripplayer = false; + SetPlayerInvincibilityFrame(180); + _SigilCall(false, teamimg, 2816+256, 512, 2816+512, 768, objPlayer, 150); + SetPlayerSpell( max(2,GetPlayerSpell()) ); + } + + case(EV_GRAZE){ + grazecounter += GetEventArgument(0); + ObjSound_Play(grazesfx); + while(grazecounter >= 10){ + SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue")+10); + grazecounter -= 10; + } + } +} + +@Finalize{ + +} + +task _MikoOption(){ + + // Offsets for 4 front options + + float offsetX1 = 90; + float offsetX2 = offsetX1 * 2; + float offsetY1 = 45; + + // Array that contains static/unchanging values for the PlayerOption + + let val = [1792, 256, 2048, 512, 0.65, 256, 1, 1, false, false, 0, true, false]; + + // Option handling (right -> rightmost -> left -> leftmost) + + float[][] offsetArray = [[offsetX1, offsetY1], [offsetX2, 0], [-offsetX1, offsetY1], [-offsetX2, 0]]; + + int opt1 = PlayerOption( + offsetArray[0][0], offsetArray[0][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int opt2 = PlayerOption( + offsetArray[1][0], offsetArray[1][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int opt3 = PlayerOption( + offsetArray[2][0], offsetArray[2][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int opt4 = PlayerOption( + offsetArray[3][0], offsetArray[3][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int[] optArray = [opt1, opt2, opt3, opt4]; + + ascent(i in -1..length(optArray)-1){ + _SwingBehaviour(optArray[i]); + } + + task _SwingBehaviour(target){ + float ang = 0; + Obj_SetRenderPriorityI(target, 42); + while(true){ + ObjRender_SetAngleZ(target, 0+20*sin(ang)); + ang += 360/120; + yield; + } + } + + int laser1 = _RenderLaser(opt1, -7, 300, GetStgFrameHeight*1.25, 65, 0, 2.6); + int laser2 = _RenderLaser(opt2, -14, 600, GetStgFrameHeight*1.25, 65, 0, 2.6); + int laser3 = _RenderLaser(opt3, 7, 300, GetStgFrameHeight*1.25, 65, 0, 2.6); + int laser4 = _RenderLaser(opt4, 14, 600, GetStgFrameHeight*1.25, 65, 0, 2.6); + + //int laser3 = _RenderLaser(opt3, 0, 300, GetStgFrameHeight*1.25, 50, 0, 5); + + float focusDist = 280; + let dummy = CreatePlayerShotA1(playerX, playerY-focusDist, 0, 0, 0, 99999, 0); + + ObjShot_SetAutoDelete(dummy, false); + ObjShot_SetIntersectionEnable(dummy, false); + + //ObjMove_AddPatternA4(laser1, 0, NO_CHANGE, 0, NO_CHANGE, NO_CHANGE, NO_CHANGE, NO_CHANGE, dummy); + //ObjMove_AddPatternA4(laser2, 0, NO_CHANGE, 0, NO_CHANGE, NO_CHANGE, NO_CHANGE, NO_CHANGE, dummy); +} + +// Miko's lasers + +// Basic player parameters + +task parameterrender(){ + + SetPlayerItemScope(120); + SetPlayerLife(9); // Debug + SetPlayerSpell(2); + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); // (original: 5.25/2.0) + SetPlayerRebirthFrame(25); + SetPlayerAutoItemCollectLine(GetStgFrameHeight/3); + SetPlayerRebirthLossFrame(0); + ObjPlayer_AddIntersectionCircleA1(objPlayer, 0, 0, 2.0, 55); + +} + +// Renders the shottype +// Player sprites + +task playerrender(){ + + // Why is this movement code so cursed jesus fucking christ + + float scale = 0.34; // Scalies + + ObjPrim_SetTexture(objPlayer, teamimg); + ObjSprite2D_SetSourceRect(objPlayer, 0, 0, 320, 384); + ObjSprite2D_SetDestCenter(objPlayer); + Obj_SetRenderPriorityI(objPlayer, 42); + ObjRender_SetScaleXYZ(objPlayer, scale, scale, 1); + + // Lower "speed" parameter = FASTER SPEED + + // FOR WHEN ONLY IDLE SPRITES ARE DONE + + loop{ + // Focused + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + frameidlemiko++; + _RenderPlayerMovement(objPlayer, frameidlemiko, 0, 1152, 320, 384, scale, 4, 5); + if (frameidlemiko >= (5*4-1)){frameidlemiko = 0;} + } + // Unfocused + else{ + frameidlebyak++; + _RenderPlayerMovement(objPlayer, frameidlebyak, 0, 0, 320, 384, scale, 5, 5); + if (frameidlebyak >= (5*5-1)){frameidlebyak = 0;} + } + yield; + } + +} + +task ByakShot(){ + + // Offsets for 4 front options + + float offsetX1 = 75; + float offsetX2 = offsetX1 * 2; + float offsetY1 = -75; + + // Array that contains static/unchanging values for the PlayerOption + + let valL = [2048, 256, 2048+256, 512, 0.32, 256, 1, 1, false, true, 6, false, true]; + let valR = [2048, 256, 2048+256, 512, 0.32, 256, 1, 1, false, true, -6, false, true]; + + // Option handling + + float[][] offsetArray = [[offsetX1, offsetY1], [offsetX2, 0], [-offsetX1, offsetY1], [-offsetX2, 0]]; + + int opt1 = PlayerOption( + offsetArray[0][0], offsetArray[0][1], + teamimg, + valR[0], valR[1], valR[2], valR[3], valR[4], + valR[5], valR[6], valR[7], valR[8], + valR[9], valR[10], + valR[11], valR[12]); + + int opt2 = PlayerOption( + offsetArray[1][0], offsetArray[1][1], + teamimg, + valR[0], valR[1], valR[2], valR[3], valR[4], + valR[5], valR[6], valR[7], valR[8], + valR[9], valR[10], + valR[11], valR[12]); + + int opt3 = PlayerOption( + offsetArray[2][0], offsetArray[2][1], + teamimg, + valL[0], valL[1], valL[2], valL[3], valL[4], + valL[5], valL[6], valL[7], valL[8], + valL[9], valL[10], + valL[11], valL[12]); + + int opt4 = PlayerOption( + offsetArray[3][0], offsetArray[3][1], + teamimg, + valL[0], valL[1], valL[2], valL[3], valL[4], + valL[5], valL[6], valL[7], valL[8], + valL[9], valL[10], + valL[11], valL[12]); + + int[] optArray = [opt1, opt2, opt3, opt4]; + + ObjRender_SetAngleX(opt1, (-1)*valR[4]); + ObjRender_SetAngleX(opt2, (-1)*valR[4]); + + ascent(i in -1..length(optArray)-1){ + _ThunderNeedle(optArray[i], 270, 7.5, 2); + } + + _ThunderNeedle(optArray[1], 135, 7.5, 2); + _ThunderNeedle(optArray[3], 45, 7.5, 2); + + //_ThunderNeedle(opt1, 270, 12, 2); + //_ThunderNeedle(opt2, 250, 5, 2); + //_ThunderNeedle(opt4, 290, 5, 2); + //_ThunderNeedle(opt3, 270, 12, 2); + + // Byakuren's shot + + task _ThunderNeedle(int target, float baseang, float tiltang, int num){ + + //float baseang = 270; + + int a = 0; + + loop{ + if(IsPermitPlayerShot && !ripplayer && GetVirtualKeyState(VK_SHOT) != KEY_FREE && GetVirtualKeyState(VK_SLOWMOVE) == KEY_FREE){ + if(shotspeed % 5 == 0){ + ascent(i in 0..num){ + float shot = CreatePlayerShotA1(ObjRender_GetX(target), ObjRender_GetY(target), 44, baseang-tiltang+a*tiltang*2, 4.1, 1.8, BYAKUREN_NEEDLE); + ObjRender_SetAlpha(shot, 255*(universalAlpha/100)); + _BulletRescalePlayer(shot, 0.7, true, 0.7); + //Fadein(shot); + a++; + if (a == num){a = 0;} + } + ObjSound_Play(basesfx); + } + } + yield; + } + + task Fadein(target){ + ascent(i in 0..5){ + //ObjRender_SetAlpha(target, Interpolate_Decelerate(180, 255, i/5)); + _BulletRescalePlayer(target, Interpolate_Decelerate(0.4, 0.7, i/5), true, Interpolate_Decelerate(0.4, 0.7,i/5)); + //ObjRender_SetBlendType(target, BLEND_ADD_ARGB); + yield; + } + ObjRender_SetBlendType(target, BLEND_ALPHA); + } + + } + +} + +// Handling of bomb +task Fadein(target, len, targetscale, targetscalehitbox){ + ascent(i in 0..len){ + //ObjRender_SetAlpha(target, Interpolate_Decelerate(180, 255, i/len)); + _BulletRescalePlayer(target, Interpolate_Decelerate(0.4, targetscale, i/len), true, Interpolate_Decelerate(1, targetscalehitbox, i/len)); + //ObjRender_SetBlendType(target, BLEND_ADD_ARGB); + yield; + } + ObjRender_SetBlendType(target, BLEND_ALPHA); +} + +task _FocusBomb(){ + + // Preparation + SetForbidPlayerShot(true); + SetForbidPlayerSpell(true); + SetPlayerInvincibilityFrame(32*3+32*3+42*3+120+45); + // Spell object + let manageObj = GetSpellManageObject(); // SPELL BEGINS + ObjSpell_Regist(manageObj); + ObjSound_Play(bombsfx); + SetPlayerSpeed(5, 5); + + float angvel = 0.75; + float revolve = 2; + float spd = 21; + float dmg = 2; + float revolvechange = 12; + + ascent(i in 0..16){ + + float angBase = rand(0, 360); + + alternative(revolve) + case(2){revolve = -2;} + case(-2){revolve = 2;} + + ascent(i in 0..12){ + float ang = angBase + 360/12 * i; + int shot = CreateShotA2(playerX, playerY, 24, ang, 0, 24, revolve, 3, 0); + Fadein(shot, 10, 1.5, 1.5); + ObjRender_SetBlendType(shot, BLEND_ADD_ARGB); + ObjShot_SetIntersectionEnable(shot, true); + ObjShot_SetPenetration(shot, 9999); + ObjShot_SetDamage(shot, 2.5); + ObjShot_SetEraseShot(shot, true); + ObjShot_SetSpellFactor(shot, true); + ObjMove_AddPatternA2(shot, 90, NO_CHANGE, NO_CHANGE, 1, 40, 0); + //ObjShot_SetDeleteFrame(shot, 120); + ObjSound_Play(inferno); + } + + ascent(i in 0..12){ + float ang = angBase + 360/12 * i; + int shot = CreateShotA2(playerX, playerY, 24, ang, 0, 24, -revolve, 3, 0); + Fadein(shot, 10, 1.5, 1.5); + ObjRender_SetBlendType(shot, BLEND_ADD_ARGB); + ObjShot_SetIntersectionEnable(shot, true); + ObjShot_SetPenetration(shot, 9999); + ObjShot_SetDamage(shot, 2.5); + ObjShot_SetEraseShot(shot, true); + ObjShot_SetSpellFactor(shot, true); + ObjMove_AddPatternA2(shot, 90, NO_CHANGE, NO_CHANGE, 1, 40, 0); + //ObjShot_SetDeleteFrame(shot, 120); + ObjSound_Play(inferno); + } + + wait(15); + } + + // Cleanup, end of spell + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); + SetForbidPlayerShot(false); + wait(60); + SetForbidPlayerSpell(false); + Obj_Delete(manageObj); // !!! IMPORTANT !!! + +} + +task _UnfocusBomb(){ + + // Preparation + SetForbidPlayerShot(true); + SetForbidPlayerSpell(true); + SetPlayerInvincibilityFrame(32*3+32*3+42*3+120+45); + // Spell object + let manageObj = GetSpellManageObject(); // SPELL BEGINS + ObjSpell_Regist(manageObj); + ObjSound_Play(bombsfx); + SetPlayerSpeed(10, 10); + + float angvel = 0.75; + float revolve = 0; + float spd = 21; + float dmg = 2; + float revolvechange = 12; + + ascent(i in 0..100){ + int shot = CreateShotA1(rand(0, GetStgFrameWidth()), -125, 36, 90, 2, 0); + + Fadein(shot, 18, 1.4, 1.4); + ObjRender_SetBlendType(shot, BLEND_ADD_ARGB); + ObjShot_SetSpinAngularVelocity(shot, 5); + ObjShot_SetIntersectionEnable(shot, true); + ObjShot_SetPenetration(shot, 9999); + ObjShot_SetDamage(shot, 3.5); + ObjShot_SetEraseShot(shot, true); + ObjShot_SetSpellFactor(shot, true); + ObjSound_Play(inferno); + + wait(3); + } + + // Cleanup, end of spell + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); + SetForbidPlayerShot(false); + wait(60); + SetForbidPlayerSpell(false); + Obj_Delete(manageObj); // !!! IMPORTANT !!! + +} + +// Screenshake function for bomb's duration - adapted from Sparen's tutorials + +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; +} + diff --git a/script/player/PrideJam_ByakMiko/ByakMiko_ShotConst.dnh b/script/player/PrideJam_ByakMiko/ByakMiko_ShotConst.dnh new file mode 100644 index 0000000..5bb9961 --- /dev/null +++ b/script/player/PrideJam_ByakMiko/ByakMiko_ShotConst.dnh @@ -0,0 +1,8 @@ +let current = GetCurrentScriptDirectory(); +let path = current ~ "ByakMiko_ShotData.dnh"; +LoadPlayerShotData(path); +// ----- + +const BYAKUREN_NEEDLE = 1; + + diff --git a/script/player/PrideJam_ByakMiko/ByakMiko_ShotData.dnh b/script/player/PrideJam_ByakMiko/ByakMiko_ShotData.dnh new file mode 100644 index 0000000..e20571e --- /dev/null +++ b/script/player/PrideJam_ByakMiko/ByakMiko_ShotData.dnh @@ -0,0 +1,40 @@ +shot_image = "./playerlib/ByakMiko_Sheet.png" + +ShotData{ + id = 0 // Dummy + rect = (0,0,0,0) + render = ALPHA + alpha = 0 + collision = 32 +} + + +// Arrow (Option) + +ShotData{ + id = 1 + rect = (2048, 0, 2304, 256) + render = ALPHA + alpha = 255 + collision = (75, 0, 0) // Hitbox of arrows is not centered on the sprite +} + +// Bomb + +ShotData{ + id = 2 + rect = (2560, 0, 2816, 256) + render = ADD_ARGB + alpha = 255 + collision = 80 // Hitbox of arrows is not centered on the sprite +} + +ShotData{ + id = 3 + rect = (2816, 0, 3072, 256) + render = ADD_ARGB + alpha = 255 + collision = 80 // Hitbox of arrows is not centered on the sprite +} + + diff --git a/script/player/PrideJam_ByakMiko/desc.txt b/script/player/PrideJam_ByakMiko/desc.txt new file mode 100644 index 0000000..e69de29 diff --git a/script/player/PrideJam_ByakMiko/playerlib/ByakMiko_Sheet.png b/script/player/PrideJam_ByakMiko/playerlib/ByakMiko_Sheet.png new file mode 100644 index 0000000..d5ab12b Binary files /dev/null and b/script/player/PrideJam_ByakMiko/playerlib/ByakMiko_Sheet.png differ diff --git a/script/player/PrideJam_ByakMiko/sound/CK Music Factory/air01.wav b/script/player/PrideJam_ByakMiko/sound/CK Music Factory/air01.wav new file mode 100644 index 0000000..bc2c0ed Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/CK Music Factory/air01.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/CK Music Factory/air02.wav b/script/player/PrideJam_ByakMiko/sound/CK Music Factory/air02.wav new file mode 100644 index 0000000..f7e5ed8 Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/CK Music Factory/air02.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/CK Music Factory/laser01.wav b/script/player/PrideJam_ByakMiko/sound/CK Music Factory/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/CK Music Factory/laser01.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/CK Music Factory/slash01.wav b/script/player/PrideJam_ByakMiko/sound/CK Music Factory/slash01.wav new file mode 100644 index 0000000..364dfca Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/CK Music Factory/slash01.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/CK Music Factory/wind01.wav b/script/player/PrideJam_ByakMiko/sound/CK Music Factory/wind01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/CK Music Factory/wind01.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/TAM Music Factory/se04.wav b/script/player/PrideJam_ByakMiko/sound/TAM Music Factory/se04.wav new file mode 100644 index 0000000..ca33890 Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/TAM Music Factory/se04.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/TAM Music Factory/status4.wav b/script/player/PrideJam_ByakMiko/sound/TAM Music Factory/status4.wav new file mode 100644 index 0000000..1227a08 Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/TAM Music Factory/status4.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/TAM Music Factory/tama2.wav b/script/player/PrideJam_ByakMiko/sound/TAM Music Factory/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/TAM Music Factory/tama2.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/bfxr_scythecall.wav b/script/player/PrideJam_ByakMiko/sound/bfxr_scythecall.wav new file mode 100644 index 0000000..99b3040 Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/bfxr_scythecall.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/bfxr_splash.wav b/script/player/PrideJam_ByakMiko/sound/bfxr_splash.wav new file mode 100644 index 0000000..6a4d49d Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/bfxr_splash.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/bfxr_teleporthigh.wav b/script/player/PrideJam_ByakMiko/sound/bfxr_teleporthigh.wav new file mode 100644 index 0000000..cc8b9ae --- /dev/null +++ b/script/player/PrideJam_ByakMiko/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/PrideJam_ByakMiko/sound/bfxr_teleportlow.wav b/script/player/PrideJam_ByakMiko/sound/bfxr_teleportlow.wav new file mode 100644 index 0000000..d55ce4b Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/bfxr_teleportlow.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/bfxr_watershoot.wav b/script/player/PrideJam_ByakMiko/sound/bfxr_watershoot.wav new file mode 100644 index 0000000..6cfced3 Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/bfxr_watershoot.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/birdcall05.wav b/script/player/PrideJam_ByakMiko/sound/birdcall05.wav new file mode 100644 index 0000000..ec6c7b9 Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/birdcall05.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/hit01.wav b/script/player/PrideJam_ByakMiko/sound/hit01.wav new file mode 100644 index 0000000..0698a04 Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/hit01.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/laser01.wav b/script/player/PrideJam_ByakMiko/sound/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/laser01.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/magic21.wav b/script/player/PrideJam_ByakMiko/sound/magic21.wav new file mode 100644 index 0000000..19714fe Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/magic21.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/slash01.wav b/script/player/PrideJam_ByakMiko/sound/slash01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/slash01.wav differ diff --git a/script/player/PrideJam_ByakMiko/sound/tama2.wav b/script/player/PrideJam_ByakMiko/sound/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/PrideJam_ByakMiko/sound/tama2.wav differ diff --git a/script/player/PrideJam_RinnoRemi/RinnoRemi_Function.dnh b/script/player/PrideJam_RinnoRemi/RinnoRemi_Function.dnh new file mode 100644 index 0000000..7aeb7b9 --- /dev/null +++ b/script/player/PrideJam_RinnoRemi/RinnoRemi_Function.dnh @@ -0,0 +1,115 @@ + +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(inferno);} + 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; + } + +} \ No newline at end of file diff --git a/script/player/PrideJam_RinnoRemi/RinnoRemi_Main.dnh b/script/player/PrideJam_RinnoRemi/RinnoRemi_Main.dnh new file mode 100644 index 0000000..d4e7534 --- /dev/null +++ b/script/player/PrideJam_RinnoRemi/RinnoRemi_Main.dnh @@ -0,0 +1,693 @@ +#TouhouDanmakufu[Player] +#ScriptVersion[3] +#ID["RinnoRemi"] +#Title["Rinnosuke Morichika & Remilia Scarlet"] +#Text["Unfocused Shot: Electronic Doombringer[r]Outbursts of fire from the Outside World's doomsday devices.[r][r]Focused Shot: Fate-Sealing Stars[r]High-speed homing stars.[r][r]Special Ability: Longer deathbomb timer."] + +//#Image["./mariremi_lib/mariremi_illust.png"] + +#ReplayName["RinnoRemi"] + +#include "script/KevinSystem/Kevin_PlayerLib.txt" +#include "script/KevinSystem/PlayerSoundLib.dnh" + +#include "./RinnoRemi_Function.dnh" +#include "./RinnoRemi_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/RinnoRemi_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); + +int frameidlerinno = 0; +int frameidleremi = 0; +int framemoverinno = 0; +int framemoveremi = 0; + +bool ripplayer = false; +float shotspeed = 0; +float bombrand = 0; + +bool bombenable = false; +bool focusactive = false; +bool ishoming = 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 + +float[] PlayerSpd = [9.5, 5.2]; + +// 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); + } + 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); + + _HitboxRender(ripplayer, objPlayer, teamimg, teamimg, 2560, 512, 2688, 640, 2816, 1024, 2816+511, 1024+511, 0.22, 0.65); + SetShotAutoDeleteClip(256, 256, 256, 256); + + // Shot functions + + //_CAVELaser(); + rinnoShot(); + _BaseShot(); + _remiOption(); + //UniversalAlphaHandle(_shotArray); + + // Shot data loading + LoadPlayerShotData(csd ~ "./RinnoRemi_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){ + 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); + //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); + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){_FocusBomb(); _SigilCall(false, teamimg, 2816+256, 512, 2816+512, 768, objPlayer, GetPlayerInvincibilityFrame());} + else{_UnfocusBomb(); + _SigilCall(false, teamimg, 2816+256, 512, 2816+512, 768, objPlayer, GetPlayerInvincibilityFrame()); + } + } + + else { + SetScriptResult(false); + } + } + + case(EV_HIT){ + ObjSound_Play(predeathsfx); + _DeathbombWarning(teamimg, [1792, 512, 1792+512, 512+512], 15, 0.75); + } + + case(EV_PLAYER_SHOOTDOWN){ + ObjSound_Play(deathsfx); + ripplayer = true; + _SigilCall(true, teamimg, 2816, 512, 2816+256, 768, objPlayer, 120); + } + + case(EV_PLAYER_REBIRTH){ + ripplayer = false; + SetPlayerInvincibilityFrame(180); + _SigilCall(false, teamimg, 2816+256, 512, 2816+512, 768, objPlayer, 150); + SetPlayerSpell( max(2,GetPlayerSpell()) ); + } + + case(EV_GRAZE){ + grazecounter += GetEventArgument(0); + ObjSound_Play(grazesfx); + while(grazecounter >= 10){ + SetAreaCommonData("PIV", "currentvalue", GetAreaCommonData("PIV", "currentvalue")+10); + grazecounter -= 10; + } + } +} + +@Finalize{ + +} + +// Homing + +task _BaseShot(){ + + loop{ + if(IsPermitPlayerShot && !ripplayer && GetVirtualKeyState(VK_SHOT) != KEY_FREE){ + if(shotspeed % 5 == 0){ + if(GetVirtualKeyState(VK_SLOWMOVE) == KEY_FREE){ + float ang2 = 270-2*9; + //float angvel = (3.6-3*0.6)*1.2; + loop(5){ + let bullet = CreatePlayerShotA1(playerX, playerY, 32, ang2, 1.4, 1.8, BASE); + Obj_SetRenderPriorityI(bullet, 39); + ObjRender_SetAlpha(bullet, 255*(universalAlpha/100)); + ObjShot_SetSpinAngularVelocity(bullet, 10); + _BulletRescalePlayer(bullet, 0.5, true, 0.8); + //angvel -= 0.6*1.2; + ang2 += 9; + } + } + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + float ang2 = 270-2*5; + //float angvel = (3.6-3*0.6)*1.2; + loop(5){ + let bullet = CreatePlayerShotA1(playerX, playerY, 32, ang2, 1.2, 1.8, BASE); + Obj_SetRenderPriorityI(bullet, 39); + ObjRender_SetAlpha(bullet, 255*(universalAlpha/100)); + ObjShot_SetSpinAngularVelocity(bullet, 10); + _BulletRescalePlayer(bullet, 0.5, true, 0.8); + //angvel -= 0.6*1.2; + ang2 += 5; + } + } + //ObjSound_Play(basesfx); + } + } + yield; + } + +} + +task _HomeShot(int shot_) { + + float duration = 1; + 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(objPlayer), enemyY - ObjMove_GetY(objPlayer)); + + // 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.75, min(60, f) / 60); + // 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; + }*/ + + 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.75, min(60, f) / 60); + // Homing speed? + ObjMove_SetAngle(shot_, Interpolate_Accelerate(shotAngle, shotAngle + angleDistance, 1)); // Interpolate_Necko + f++; + yield; + } + ObjShot_SetAutoDelete(shot_, true); + ObjMove_SetAngularVelocity(shot_, 0); + homingBool = false; + } + } + + yield; + } +} + +task _SwingBehaviour(target){ + float ang = 0; + Obj_SetRenderPriorityI(target, 42); + while(true){ + ObjRender_SetAngleZ(target, 0+20*sin(ang)); + ang += 360/120; + yield; + } + } + +task _remiOption(){ + + // Offsets for 4 front options + + float offsetX1 = 150; + float offsetX2 = offsetX1 * 2; + float offsetY1 = 90; + + // Array that contains static/unchanging values for the PlayerOption + + let val = [2048, 256, 2304, 512, 0.6, 256, 1, 1, false, false, 0, true, false]; + + // Option handling (right -> rightmost -> left -> leftmost) + + float[][] offsetArray = [[offsetX1, offsetY1], [offsetX2, 0], [-offsetX1, offsetY1], [-offsetX2, 0]]; + + int opt1 = PlayerOption( + offsetArray[0][0], offsetArray[0][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int opt2 = PlayerOption( + offsetArray[1][0], offsetArray[1][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int opt3 = PlayerOption( + offsetArray[2][0], offsetArray[2][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int opt4 = PlayerOption( + offsetArray[3][0], offsetArray[3][1], + teamimg, + val[0], val[1], val[2], val[3], val[4], + val[5], val[6], val[7], val[8], + val[9], val[10], + val[11], val[12]); + + int[] optArray = [opt1, opt2, opt3, opt4]; + + ascent(i in -1..length(optArray)-1){ + _SwingBehaviour(optArray[i]); + _HomingStars(optArray[i]); + } + + task _HomingStars(option){ + + loop{ + if(shotspeed % 5 == 0 && GetVirtualKeyState(VK_SHOT) != KEY_FREE && IsPermitPlayerShot && !ripplayer){ + + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + + float x = ObjRender_GetX(option); + float y = ObjRender_GetY(option); + + ascent(i in -1..1){ + let shotA = CreatePlayerShotA1(-50+x+25-50*i, y, 50, 270, 1.37, 1.25, LOCKON_KNIFE); + //ObjMove_AddPatternA2(shotA, 1, 5, NO_CHANGE, -0.1, 3.75, rand(-0.4, 0.4)); + + //ObjMove_AddPatternA2(shotA, 1, NO_CHANGE, NO_CHANGE, 25, 50, 0); + _BulletRescalePlayer(shotA, 0.7, true, 1); + ObjRender_SetAlpha(shotA, 255*(universalAlpha/100)); + ObjSound_Play(inferno); + _HomeShot(shotA); + //Fadein(shotA, 10); + } + + } + + } + + yield; + } + + } + +} + +// Basic player parameters + +task parameterrender(){ + + SetPlayerItemScope(120); + SetPlayerLife(9); // Debug + SetPlayerSpell(2); + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); // (original: 5.25/2.0) + SetPlayerRebirthFrame(12); + SetPlayerAutoItemCollectLine(GetStgFrameHeight/3); + SetPlayerRebirthLossFrame(0); + ObjPlayer_AddIntersectionCircleA1(objPlayer, 0, 0, 1.25, 40); + +} + +// Renders the shottype +// Player sprites + +task playerrender(){ + + // Why is this movement code so cursed jesus fucking christ + + float scale = 0.39; // Scalies + + ObjPrim_SetTexture(objPlayer, teamimg); + ObjSprite2D_SetSourceRect(objPlayer, 0, 0, 320, 384); + ObjSprite2D_SetDestCenter(objPlayer); + Obj_SetRenderPriorityI(objPlayer, 42); + ObjRender_SetScaleXYZ(objPlayer, scale, scale, 1); + + // Lower "speed" parameter = FASTER SPEED + + // FOR WHEN ONLY IDLE SPRITES ARE DONE + + loop{ + // Focused + if(GetVirtualKeyState(VK_SLOWMOVE) != KEY_FREE){ + frameidleremi++; + _RenderPlayerMovement(objPlayer, frameidleremi, 0, 1152, 320, 384, scale, 4, 6); + if (frameidleremi >= (5*4-1)){frameidleremi = 0;} + } + // Unfocused + else{ + frameidlerinno++; + _RenderPlayerMovement(objPlayer, frameidlerinno, 0, 0, 320, 384, scale, 4, 6); + if (frameidlerinno >= (5*4-1)){frameidlerinno = 0;} + } + yield; + } + +} + +task rinnoShot(){ + + // Offsets for 4 front options + + float offsetX1 = 90; + + // Array that contains static/unchanging values for the PlayerOption + + let valR = [1792, 256, 2048, 512, 0.5, 256, 1, 1, false, false, 6, false, true]; + + // Option handling + + float[][] offsetArray = [[offsetX1, 0], [-offsetX1, 0]]; + + /*int opt1 = PlayerOption( + offsetArray[0][0], offsetArray[0][1], + teamimg, + valR[0], valR[1], valR[2], valR[3], valR[4], + valR[5], valR[6], valR[7], valR[8], + valR[9], valR[10], + valR[11], valR[12]); + + int opt2 = PlayerOption( + offsetArray[1][0], offsetArray[1][1], + teamimg, + valR[0], valR[1], valR[2], valR[3], valR[4], + valR[5], valR[6], valR[7], valR[8], + valR[9], valR[10], + valR[11], valR[12]);*/ + + int opt3 = PlayerOption( + 0, 150, + teamimg, + valR[0], valR[1], valR[2], valR[3], valR[4], + valR[5], valR[6], valR[7], valR[8], + valR[9], valR[10], + valR[11], valR[12]); + + //int[] optArray = [opt1, opt2]; + + float angle = 255; + + /*ascent(i in -1..length(optArray)-1){ + _ThunderNeedle(optArray[i], angle, 10, 4); + _ThunderNeedle(optArray[i], 90, 7.5, 2.5); + _SwingBehaviour(optArray[i]); + angle += 35; + }*/ + + _ThunderNeedle(opt3, 15, 270, 10, 8, 4.2); + _ThunderNeedle(opt3, -15, 90, 15, 4, 4.4); + _SwingBehaviour(opt3); + + task _ThunderNeedle(int target, float yoffset, float baseang, float tiltang, int num, float dmg){ + + //float baseang = 270; + + //int a = trunc(-num/2); + + // Odd numbers only + + loop{ + if(IsPermitPlayerShot && !ripplayer && GetVirtualKeyState(VK_SHOT) != KEY_FREE && GetVirtualKeyState(VK_SLOWMOVE) == KEY_FREE){ + if(shotspeed % 5 == 0){ + ascent(i in trunc(-num/2)..trunc(num/2)+1){ + float shot = CreatePlayerShotA1(ObjRender_GetX(target), ObjRender_GetY(target)+yoffset, 65, baseang-tiltang*i, dmg, 1.0, ELECTRIC_FIRE_ALT); + ObjRender_SetAlpha(shot, 255*(universalAlpha/100)); + Obj_SetRenderPriorityI(shot, 39); + _BulletRescalePlayer(shot, 0.55, true, 1); + } + } + if(shotspeed % 5 == 0){ObjSound_Play(basesfx);} + } + 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 _FocusBomb(){ + + // Preparation + SetForbidPlayerShot(true); + SetForbidPlayerSpell(true); + SetPlayerInvincibilityFrame(32*3+32*3+42*3+120+45); + // Spell object + let manageObj = GetSpellManageObject(); // SPELL BEGINS + ObjSpell_Regist(manageObj); + ObjSound_Play(bombsfx); + SetPlayerSpeed(PlayerSpd[1]-2, PlayerSpd[1]-2); + + float angvel = 0.75; + float revolve = 0; + float spd = 21; + float dmg = 2; + float revolvechange = 12; + + ascent(i in 0..40){ + + int shot = CreateShotA2(playerX, playerY, 25, rand(260, 280), rand(-1.5, -1), 0.5, HOMING_STAR, 15); + //_BulletRescalePlayer(shot, 3, true, 1); + ObjShot_SetSpinAngularVelocity(shot, 6); + Fadein(shot, 20, 2, 2); + ObjRender_SetBlendType(shot, BLEND_ADD_ARGB); + ObjMove_AddPatternA2(shot, 30, NO_CHANGE, NO_CHANGE, 0.8, 32, 0); + ObjShot_SetIntersectionEnable(shot, true); + ObjShot_SetPenetration(shot, 9999); + ObjShot_SetDamage(shot, 2); + ObjShot_SetEraseShot(shot, true); + ObjShot_SetSpellFactor(shot, true); + ObjSound_Play(inferno); + wait(5); + + } + + // Cleanup, end of spell + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); + SetForbidPlayerShot(false); + wait(60); + SetForbidPlayerSpell(false); + Obj_Delete(manageObj); // !!! IMPORTANT !!! + +} + +task _UnfocusBomb(){ + + // Preparation + SetForbidPlayerShot(true); + SetForbidPlayerSpell(true); + SetPlayerInvincibilityFrame(32*3+32*3+42*3+120+45); + // Spell object + let manageObj = GetSpellManageObject(); // SPELL BEGINS + ObjSpell_Regist(manageObj); + ObjSound_Play(bombsfx); + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[0]); + + float angvel = 0.75; + float revolve = 0; + float spd = 21; + float dmg = 2; + float revolvechange = 12; + + int hakkero = CreatePlayerShotA1(playerX, playerY, 0, 0, 12, 999999, 4); + ObjShot_SetIntersectionEnable(hakkero, true); + ObjShot_SetEraseShot(hakkero, true); + ObjShot_SetSpellFactor(hakkero, true); + ObjShot_SetSpinAngularVelocity(hakkero, 8); + + async{ + ascent(i in 0..45){ + _BulletRescalePlayer(hakkero, Interpolate_Decelerate(0.5, 2.25, i/45), true, 1); + ObjRender_SetAlpha(hakkero, Interpolate_Decelerate(0, 255, i/45)); + yield; + } + } + + ascent(i in 0..240){ + yield; + } + + // Cleanup, end of spell + ObjShot_FadeDelete(hakkero); + SetPlayerSpeed(PlayerSpd[0], PlayerSpd[1]); + SetForbidPlayerShot(false); + wait(60); + SetForbidPlayerSpell(false); + Obj_Delete(manageObj); // !!! IMPORTANT !!! + +} + +// Screenshake function for bomb's duration - adapted from Sparen's tutorials + +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; +} + diff --git a/script/player/PrideJam_RinnoRemi/RinnoRemi_ShotConst.dnh b/script/player/PrideJam_RinnoRemi/RinnoRemi_ShotConst.dnh new file mode 100644 index 0000000..a89ef27 --- /dev/null +++ b/script/player/PrideJam_RinnoRemi/RinnoRemi_ShotConst.dnh @@ -0,0 +1,12 @@ +let current = GetCurrentScriptDirectory(); +let path = current ~ "RinnoRemi_ShotData.dnh"; +LoadPlayerShotData(path); +// ----- + +const HOMING_STAR = 1; +const ELECTRIC_FIRE = 2; +const BASE = 3; +const ELECTRIC_FIRE_ALT = 5; +const LOCKON_KNIFE = 6; + + diff --git a/script/player/PrideJam_RinnoRemi/RinnoRemi_ShotData.dnh b/script/player/PrideJam_RinnoRemi/RinnoRemi_ShotData.dnh new file mode 100644 index 0000000..8d78eac --- /dev/null +++ b/script/player/PrideJam_RinnoRemi/RinnoRemi_ShotData.dnh @@ -0,0 +1,64 @@ +shot_image = "./playerlib/RinnoRemi_Sheet.png" + +ShotData{ + id = 0 // Dummy + rect = (0,0,0,0) + render = ALPHA + alpha = 0 + collision = 32 +} + +// Homing stars + +ShotData{ + id = 1 + rect = (1792, 0, 2048, 256) + render = ALPHA + alpha = 255 + collision = (75, 0, 0) // Hitbox of arrows is not centered on the sprite +} + +// Unfocused fire + +ShotData{ + id = 2 + rect = (2048, 0, 2304, 256) + render = ALPHA + alpha = 200 + collision = (52, 0, 0) // Hitbox of arrows is not centered on the sprite +} + + +ShotData{ + id = 3 + rect = (2304, 0, 2560, 256) + render = ALPHA + alpha = 200 + collision = (75, 0, 0) // Hitbox of arrows is not centered on the sprite +} + +ShotData{ + id = 5 + rect = (2560, 0, 2816, 384) + render = ALPHA + alpha = 210 + collision = (115, 0, 128) // Hitbox of arrows is not centered on the sprite +} + +ShotData{ + id = 6 + rect = (2816, 0, 3072, 256) + render = ALPHA + alpha = 225 + collision = (75, 0, 0) // Hitbox of arrows is not centered on the sprite +} + +// Bomb + +ShotData{ + id = 4 + rect = (3328, 1024, 3840, 1536) + render = ADD_ARGB + alpha = 255 + collision = 160 +} \ No newline at end of file diff --git a/script/player/PrideJam_RinnoRemi/desc.txt b/script/player/PrideJam_RinnoRemi/desc.txt new file mode 100644 index 0000000..e69de29 diff --git a/script/player/PrideJam_RinnoRemi/playerlib/ByakMiko_Sheet.png b/script/player/PrideJam_RinnoRemi/playerlib/ByakMiko_Sheet.png new file mode 100644 index 0000000..d5ab12b Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/playerlib/ByakMiko_Sheet.png differ diff --git a/script/player/PrideJam_RinnoRemi/playerlib/RinnoRemi_Sheet.png b/script/player/PrideJam_RinnoRemi/playerlib/RinnoRemi_Sheet.png new file mode 100644 index 0000000..fad65e8 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/playerlib/RinnoRemi_Sheet.png differ diff --git a/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/air01.wav b/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/air01.wav new file mode 100644 index 0000000..bc2c0ed Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/air01.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/air02.wav b/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/air02.wav new file mode 100644 index 0000000..f7e5ed8 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/air02.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/laser01.wav b/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/laser01.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/slash01.wav b/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/slash01.wav new file mode 100644 index 0000000..364dfca Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/slash01.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/wind01.wav b/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/wind01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/CK Music Factory/wind01.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/TAM Music Factory/se04.wav b/script/player/PrideJam_RinnoRemi/sound/TAM Music Factory/se04.wav new file mode 100644 index 0000000..ca33890 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/TAM Music Factory/se04.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/TAM Music Factory/status4.wav b/script/player/PrideJam_RinnoRemi/sound/TAM Music Factory/status4.wav new file mode 100644 index 0000000..1227a08 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/TAM Music Factory/status4.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/TAM Music Factory/tama2.wav b/script/player/PrideJam_RinnoRemi/sound/TAM Music Factory/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/TAM Music Factory/tama2.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/bfxr_scythecall.wav b/script/player/PrideJam_RinnoRemi/sound/bfxr_scythecall.wav new file mode 100644 index 0000000..99b3040 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/bfxr_scythecall.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/bfxr_splash.wav b/script/player/PrideJam_RinnoRemi/sound/bfxr_splash.wav new file mode 100644 index 0000000..6a4d49d Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/bfxr_splash.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/bfxr_teleporthigh.wav b/script/player/PrideJam_RinnoRemi/sound/bfxr_teleporthigh.wav new file mode 100644 index 0000000..cc8b9ae --- /dev/null +++ b/script/player/PrideJam_RinnoRemi/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/PrideJam_RinnoRemi/sound/bfxr_teleportlow.wav b/script/player/PrideJam_RinnoRemi/sound/bfxr_teleportlow.wav new file mode 100644 index 0000000..d55ce4b Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/bfxr_teleportlow.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/bfxr_watershoot.wav b/script/player/PrideJam_RinnoRemi/sound/bfxr_watershoot.wav new file mode 100644 index 0000000..6cfced3 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/bfxr_watershoot.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/birdcall05.wav b/script/player/PrideJam_RinnoRemi/sound/birdcall05.wav new file mode 100644 index 0000000..ec6c7b9 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/birdcall05.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/hit01.wav b/script/player/PrideJam_RinnoRemi/sound/hit01.wav new file mode 100644 index 0000000..0698a04 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/hit01.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/laser01.wav b/script/player/PrideJam_RinnoRemi/sound/laser01.wav new file mode 100644 index 0000000..b41bae2 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/laser01.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/magic21.wav b/script/player/PrideJam_RinnoRemi/sound/magic21.wav new file mode 100644 index 0000000..19714fe Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/magic21.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/slash01.wav b/script/player/PrideJam_RinnoRemi/sound/slash01.wav new file mode 100644 index 0000000..5941d52 Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/slash01.wav differ diff --git a/script/player/PrideJam_RinnoRemi/sound/tama2.wav b/script/player/PrideJam_RinnoRemi/sound/tama2.wav new file mode 100644 index 0000000..d542bbd Binary files /dev/null and b/script/player/PrideJam_RinnoRemi/sound/tama2.wav differ diff --git a/script/player/default_player/Default_Player_MagicCircle.png b/script/player/default_player/Default_Player_MagicCircle.png new file mode 100644 index 0000000..0e0d6a1 Binary files /dev/null and b/script/player/default_player/Default_Player_MagicCircle.png differ diff --git a/script/player/default_player/Default_Player_Rumia.png b/script/player/default_player/Default_Player_Rumia.png new file mode 100644 index 0000000..677fbbd Binary files /dev/null and b/script/player/default_player/Default_Player_Rumia.png differ diff --git a/script/player/default_player/Default_Player_Rumia.txt b/script/player/default_player/Default_Player_Rumia.txt new file mode 100644 index 0000000..978a0e3 Binary files /dev/null and b/script/player/default_player/Default_Player_Rumia.txt differ diff --git a/script/player/default_player/Default_Player_RumiaShot.png b/script/player/default_player/Default_Player_RumiaShot.png new file mode 100644 index 0000000..0dba4c5 Binary files /dev/null and b/script/player/default_player/Default_Player_RumiaShot.png differ diff --git a/script/player/default_player/Default_Player_RumiaShotData.txt b/script/player/default_player/Default_Player_RumiaShotData.txt new file mode 100644 index 0000000..a592a8c Binary files /dev/null and b/script/player/default_player/Default_Player_RumiaShotData.txt differ diff --git a/script/player/default_player/Default_Player_RumiaSpell.png b/script/player/default_player/Default_Player_RumiaSpell.png new file mode 100644 index 0000000..c9d82dd Binary files /dev/null and b/script/player/default_player/Default_Player_RumiaSpell.png differ diff --git a/script/player/default_player/Default_Player_Rumia_Select.png b/script/player/default_player/Default_Player_Rumia_Select.png new file mode 100644 index 0000000..695d881 Binary files /dev/null and b/script/player/default_player/Default_Player_Rumia_Select.png differ diff --git a/script/player/default_player/laser_fx.png b/script/player/default_player/laser_fx.png new file mode 100644 index 0000000..ff8f68a Binary files /dev/null and b/script/player/default_player/laser_fx.png differ diff --git a/script/player/default_player/lasers.dnh b/script/player/default_player/lasers.dnh new file mode 100644 index 0000000..3c995df --- /dev/null +++ b/script/player/default_player/lasers.dnh @@ -0,0 +1,322 @@ +// Lasers that don't penetrate +// Can be pasted into default player Rumia by adding `TLasers();` to @Initialize +// Activation logic is focused-shooting with a slight delay, similar to CAVE games. +// "RemovePLaserGfx()" can go into shutting-down (probably not necessary). +// Made by razzy + +task TLasers{ + + 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 to 0. + + let laserLimit = 15; + let laserMode=-laserLimit; + + loop{ + if(IsPermitPlayerShot + && GetPlayerState!=STATE_HIT + && GetPlayerState!=STATE_DOWN + && GetPlayerState!=STATE_END + && (GetVirtualKeyState(VK_SHOT)==KEY_PUSH || GetVirtualKeyState(VK_SHOT)==KEY_HOLD) + ){ + if(GetVirtualKeyState(VK_SLOWMOVE)==KEY_PUSH || GetVirtualKeyState(VK_SLOWMOVE)==KEY_HOLD){ + laserMode=min(0,laserMode+1); + } + else{ + // reset laser delay when slowmove is let go + laserMode=-laserLimit; + } + + 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, 2, true, 2, 2); + } + odd=-odd; + } + //PlaySnd(SND_p_shot, 93); + } + } + else{ + // reset laser delay when fire is let go + // KEV: Unnecessary if the laser fires immediately + 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, IsStrongLaser, 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: 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. + let damager = ObjShot_Create(OBJ_STRAIGHT_LASER); + ObjShot_SetGraphic(damager, 1); + Obj_SetVisible(damager, false); + ObjShot_Regist(damager); + ObjShot_SetDamage(damager, dmg); + ObjShot_SetPenetration(damager, 8); + ObjLaser_SetLength(damager, 0); + ObjLaser_SetIntersectionWidth(damager, 64*width); + ObjLaser_SetRenderWidth(damager, 64*vwidth); + ObjStLaser_SetAngle(damager, ang); + 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(!Obj_IsDeleted(damager) // KEV: The four following states can be reduced to !ripplayer in my player scripts + && IsPermitPlayerShot + && GetPlayerState!=STATE_HIT + && GetPlayerState!=STATE_DOWN + && GetPlayerState!=STATE_END // Reduce these below to != KEY_FREE + && (GetVirtualKeyState(VK_SHOT)==KEY_PUSH || GetVirtualKeyState(VK_SHOT)==KEY_HOLD) + && (GetVirtualKeyState(VK_SLOWMOVE)==KEY_PUSH || GetVirtualKeyState(VK_SLOWMOVE)==KEY_HOLD) + ){ + CheckLaserIntersection; + + // Set the laser's position and length + ObjMove_SetPosition(damager, ObjRender_GetX(obj)+xoff,ObjRender_GetY(obj)+yoff); + len = min(maxLen, len+spd); + ObjLaser_SetLength(damager, len); + 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>8){ + MakeLaserGfxFrame; + len=max(0,len-spd); + ObjLaser_SetLength(damager, len); + CheckLaserIntersection; + yield; + } + Obj_Delete(damager); + + function MakeLaserGfxFrame(){ + let hyper=0; + 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. + + (The color values should be unnecessary.) + + */ + + // ObjStLaser_SetEndGraphic (ph3sx) may come in handy for the base/tips. + + // !IsStrongLaser = 0, IsStrongLaser = 1 + + PLaserGfxFrameLaser(lasGfxObj[0], 32+hyper*32+!IsStrongLaser*64, scroll, 63+hyper*32+!IsStrongLaser*64, (len-1)/4+scroll, 64, ObjMove_GetX(damager)+cosine*24, ObjMove_GetY(damager)+sine*24, ang+90, vwidth*rand(0.75,1.0),gLen/64, 255, 255, 255, 255); + + PLaserGfxFrameLaser(lasGfxObj[1], 32+hyper*32+!IsStrongLaser*64, scroll, 63+hyper*32+!IsStrongLaser*64, (len-1)/4+scroll, 64, ObjMove_GetX(damager)+cosine*24, ObjMove_GetY(damager)+sine*24, ang+90, vwidth*rand(0.75,1.0), gLen/64, 255, 255, 255, 48); + + PLaserGfxFrame(lasGfxObj[2], 160, 0, 191, 31, ObjMove_GetX(damager)+cosine*24, ObjMove_GetY(damager)+sine*24, ang+90, vwidth+rand(0.4, 0.5), 6, 255,255,255, 255); // Base of laser + + PLaserGfxFrame(lasGfxObj[2], 160, 32, 191, 63, ObjMove_GetX(damager)+cosine*gLen2, ObjMove_GetY(damager)+sine*gLen2, ang+90, vwidth+rand(0.4, 0.5), 6, 255, 255, 255, 255);// Tip of laser + + scroll += 3; // Scrolls the laser's graphic. + + } + + 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(!IsStrongLaser || 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. + + (I don't know the order the hitboxes will be sorted in the array, though. For all I know, coords[0][1] may be the second hitbox's y (32)...?) + + */ + 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 + + if(length(closest) > 0){ + let dist=closest[2]-16; + len=max(0,dist); + } + } + } + } // 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() ~ "laser_fx.png"; + LoadTexture(imgLaser); + + ascent(i in 0..3){ + let gfx = ObjPrim_Create(OBJ_SPRITE_LIST_2D); + ObjPrim_SetTexture(gfx, imgLaser); + Obj_SetRenderPriorityI(gfx, 41); + lasGfxObj = lasGfxObj~[gfx]; + } + ObjRender_SetBlendType(lasGfxObj[1], BLEND_ADD_ARGB); + Obj_SetRenderPriorityI(lasGfxObj[2], 42); + + while(true){ + ascent(i in 0..length(lasGfxObj)){ + ObjSpriteList2D_ClearVertexCount(lasGfxObj[i]); + } + yield; + } +} + +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(gfxObj, u, v, u2, v2, x, y, ang, sx, sy, rd, gn, bl, al){ + if(gfxObj==ID_INVALID){return;} + + ObjRender_SetPosition(gfxObj, x, y, 0); + ObjRender_SetAngleZ(gfxObj, ang); + ObjRender_SetScaleXYZ(gfxObj, sx, sy, 1); + ObjRender_SetColor(gfxObj, rd, gn, bl); + ObjRender_SetAlpha(gfxObj, al); + ObjSpriteList2D_SetSourceRect(gfxObj, u, v, u2, v2); + ObjSpriteList2D_SetDestCenter(gfxObj); + ObjSpriteList2D_AddVertex(gfxObj); +} + +task PLaserGfxFrameLaser(gfxObj, u, v, u2, v2, ry, x, y, ang, sx, sy, rd, gn, bl, al){ + if(gfxObj==ID_INVALID){return;} + + ObjRender_SetPosition(gfxObj, x,y,0); + ObjRender_SetAngleZ(gfxObj, ang); + ObjRender_SetScaleXYZ(gfxObj, sx ,sy, 1); + ObjRender_SetColor(gfxObj, rd,gn,bl); + ObjRender_SetAlpha(gfxObj, al); + ObjSpriteList2D_SetSourceRect(gfxObj, u, v, u2, v2); + let rx=(u2-u)/2; + ObjSpriteList2D_SetDestRect(gfxObj, -rx,0,rx,-ry); + ObjSpriteList2D_AddVertex(gfxObj); +} + + 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..67c1aa1 --- /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/ExRumia/ExRumia_Package_Main.txt + +//-------------------------------------------------------------- +//Window Title +// The text to display on the window title. +//window.title = ExRumia Package + +//-------------------------------------------------------------- +//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 = 1920 +screen.height = 1080 + +//-------------------------------------------------------------- +//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