SupersonicXX9

Supersonic's Complex Hit Detection (for Rivals of Aether)

Jul 24th, 2020 (edited)
1,841
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.     Supersonic's Complex Hit Detection script v2
  3.     (now featuring instance_place_list)
  4.    
  5.     While not required, I would like it if you credit me for
  6.     using this hit detection code.
  7.    
  8.     This code takes into account the following:
  9.         - Hitbox Priority
  10.         - Hitbox Groups
  11.         - Hit Lockout
  12.         - (optional) Teams
  13.         - (optional) Self Hitting
  14.    
  15.     and should be much easier to customize than my old code, as the on hit stuff
  16.     has been put into a single function for easy editing.
  17.    
  18.     The original code that was passed around had some issues with it and it
  19.     wasn't ever actually meant to be released publicly in the state it was in,
  20.     but that's okay I suppose.
  21.  
  22.     To use it, simply copy and paste the code below to their respective files and, whenever you would like to
  23.     detect hitboxes, call hit_detection(); in article[index]_update.gml.
  24.     To customize what happens when the article is hit, edit the on_hit function in article[index]_update.gml.
  25.     To customize what hitboxes can hit the article, modify the filters function in article[index]_update.gml.
  26.     I've added a couple useful commented out filters for disabling the player hitting the article and teammates
  27.     hitting the article, to serve as examples.
  28. */
  29.  
  30. ///THE ACTUAL CODE IS BELOW
  31.  
  32. ///      article[index]_init.gml
  33. //You may put this code anywhere in your article init.
  34.  
  35. //make hbox_group array (the old version was really bad because the array actually affected all players no matter what lol)
  36. hbox_group = array_create(4,0);
  37. var i1 = 0;
  38. var i2 = 0;
  39. repeat(4) {
  40.     hbox_group[@i1] = array_create(50,0);
  41.     repeat(50) {
  42.         hbox_group[@i1][@i2] = array_create(10,0);
  43.         i2++;
  44.     }
  45.     i2 = 0;
  46.     i1++;
  47. }
  48.  
  49. hitstun = 0;
  50. hitstun_full = 0;
  51.  
  52. kb_adj = 1;
  53. kb_dir = 0;
  54. orig_knock = 0;
  55.  
  56. hit_lockout = 0;
  57.  
  58. article_should_lockout = true; //set to false if you don't want hit lockout.
  59.  
  60. ///     article[index]_update.gml
  61.  
  62. //Put this code at the bottom of the file.
  63. #define on_hit(hbox)
  64. // This is the code the article should run on hit.
  65. // Edit this to have the desired functions when your article is hit by a hitbox.
  66. // hbox refers to the pHitBox object that hit the article.
  67. // hit_player_obj (usually) refers to the player that hit the article.
  68. // hit_player_num refers to the player's number that hit the article.
  69.  
  70. hit_player_obj = hbox.player_id;
  71. hit_player_num = hbox.player;
  72.  
  73. //Default Hitpause Calculation
  74. //You probably want this stuff because it makes the hit feel good.
  75. if hbox.type == 1 {
  76.     var desired_hitstop = clamp(hbox.hitpause + hbox.damage * hbox.hitpause_growth * 0.05, 0, 20);
  77.     with hit_player_obj {
  78.         if !hitpause {
  79.             old_vsp = vsp;
  80.             old_hsp = hsp;
  81.         }
  82.         hitpause = true;
  83.         has_hit = true;
  84.         if hitstop < desired_hitstop {
  85.             hitstop = desired_hitstop;
  86.             hitstop_full = desired_hitstop;
  87.         }
  88.     }
  89. }
  90. // This puts the ARTICLE in hitpause.
  91. // If your article does not already account for being in hitpause, either make it stop what it's doing in hitpause
  92. // or comment out the line below.
  93. hitstop = floor(desired_hitstop);
  94.  
  95.  
  96. //Hit Lockout
  97. if article_should_lockout hit_lockout = hbox.no_other_hit;
  98.  
  99. //Default Hitstun Calculation
  100. hitstun = (hbox.kb_value * 4 * ((kb_adj - 1) * 0.6 + 1) + hbox.damage * 0.12 * hbox.kb_scale * 4 * 0.65 * kb_adj) + 12;
  101. hitstun_full = hitstun;
  102.            
  103. //Default Knockback Calculation
  104.  
  105. // if other.force_flinch && !other.free orig_knock = 0; //uncomment this line for grounded articles.
  106. if hbox.force_flinch orig_knock = 0.3; //comment out this line for grounded articles.
  107. else orig_knock = hbox.kb_value + hbox.damage * hbox.kb_scale * 0.12 * kb_adj;
  108. kb_dir = get_hitbox_angle(hbox);
  109.  
  110. hsp = lengthdir_x(orig_knock, kb_dir);
  111. vsp = lengthdir_y(orig_knock, kb_dir);
  112.  
  113. //Default hit stuff
  114. sound_play(hbox.sound_effect);
  115. //ty nart :p
  116. var fx_x = lerp(hbox.x, x, 0.5) + hbox.hit_effect_x*hbox.spr_dir;
  117. var fx_y = lerp(hbox.y, y, 0.5) + hbox.hit_effect_y;
  118. with hit_player_obj { // use a with so that it's shaded correctly
  119.     var temp_fx = spawn_hit_fx(fx_x, fx_y, hbox.hit_effect);
  120.     temp_fx.hit_angle = other.kb_dir;
  121.     temp_fx.kb_speed = other.orig_knock;
  122. }
  123.  
  124. #define filters(hbox)
  125. //These are the filters that check whether a hitbox should be able to hit the article.
  126. //Feel free to tweak this as necessary.
  127. with hbox {
  128.     var player_equal = player == other.player_id.player;
  129.     var team_equal = get_player_team(player) == get_player_team(other.player_id.player);
  130.     return ("owner" not in self || owner != other) //check if the hitbox was created by this article
  131.         && hit_priority != 0 && hit_priority <= 10
  132.         && (groundedness == 0 || groundedness == 1+other.free)
  133.         //&& (!player_equal) //uncomment to prevent the article from being hit by its owner.
  134.         //&& ( (get_match_setting(SET_TEAMS) && (get_match_setting(SET_TEAMATTACK) || !team_equal) ) || player_equal) //uncomment to prevent the article from being hit by its owner's team.
  135. }
  136.  
  137. #define create_article_hitbox(attack, hbox_num, _x, _y)
  138. //Use this function to easily create hitboxes that ignore the article's hit detection.
  139. var hbox = create_hitbox(attack, hbox_num, floor(_x), floor(_y))
  140. hbox.owner = self;
  141. return hbox;
  142.  
  143. #define hit_detection
  144. //Code by Supersonic#9999
  145. //DO NOT modify this function unless you know what you're doing. This does the actual detection, while
  146. //the other functions determine how and what the hit detection interacts with.
  147. //hbox group management
  148. with (oPlayer)
  149.     if state == clamp(state, 5, 6) && window == 1 && window_timer == 1 {
  150.         other.hbox_group[@ player-1][@ attack] = array_create(10,0);
  151.     }
  152.  
  153. //hit lockout stuff
  154. if hit_lockout > 0 {
  155.     hit_lockout--;
  156.     return;
  157. }
  158. //get colliding hitboxes
  159. var hitbox_list = ds_list_create();
  160.  
  161. var num = instance_place_list(floor(x), floor(y), pHitBox, hitbox_list, false);
  162. var final_hbox = noone;
  163. var hit_variable = `hit_article_${id}`;
  164. if num == 0 {
  165.     ds_list_destroy(hitbox_list);
  166.     return;
  167. }
  168. if num == 1 {
  169.     //no priority checks if only one hitbox is found
  170.     var hbox = hitbox_list[|0]
  171.     var group = hbox.hbox_group
  172.     if hit_variable not in hbox
  173.         if (group == -1 || ( group != -1 && hbox_group[@ hbox.orig_player-1][@ hbox.attack][@ group] == 0)) {
  174.             if filters(hbox) {
  175.                 final_hbox = hbox;
  176.             } else {
  177.                 //hitbox doesn't meet collision criteria. since this usually doesn't change, omit it.
  178.                 variable_instance_set(hbox, hit_variable, true);
  179.             }
  180.         } else {
  181.             //fake hit if group has already hit; optimization thing
  182.             variable_instance_set(hbox, hit_variable, true);
  183.         }
  184. } else {
  185.     var highest_priority = 0;
  186.     var highest_priority_owner = -1;
  187.     var highest_priority_hbox = noone;
  188.     for (var i = 0; i < ds_list_size(hitbox_list); i++) {
  189.         var hbox = hitbox_list[|i]
  190.         var group = hbox.hbox_group
  191.         if hit_variable not in hbox
  192.             //group check
  193.             if (group == -1 || ( group != -1 && hbox_group[@ hbox.orig_player-1][@ hbox.attack][@ group] == 0)) {
  194.                 if filters(hbox) {
  195.                     if hbox.hit_priority > highest_priority {
  196.                         highest_priority = hbox.hit_priority;
  197.                         highest_priority_owner = hbox.player;
  198.                         highest_priority_hbox = hbox;
  199.                     }
  200.                 } else {
  201.                     //hitbox doesn't meet collision criteria. since this usually doesn't change, omit it.
  202.                     variable_instance_set(hbox, hit_variable, true);
  203.                 }
  204.             } else {
  205.                 //fake hit if group has already hit; optimization thing
  206.                 variable_instance_set(hbox, hit_variable, true);
  207.             }
  208.     }
  209.     if highest_priority != 0 {
  210.         final_hbox = highest_priority_hbox;
  211.     }
  212. }
  213.  
  214. if final_hbox != noone {
  215.     on_hit(final_hbox);
  216.     variable_instance_set(final_hbox, hit_variable, true);
  217.     if final_hbox.hbox_group != -1 hbox_group[@ final_hbox.orig_player-1][@ final_hbox.attack][@ final_hbox.hbox_group] = 1;
  218. }
  219.  
  220. //clear hitbox list
  221. //ds_list_clear(hitbox_list)
  222. ds_list_destroy(hitbox_list);
  223.  
Advertisement
Add Comment
Please, Sign In to add comment