Advertisement
RightSorcerer

Untitled

Apr 16th, 2023
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.04 KB | None | 0 0
  1. extends Spatial
  2.  
  3. var packed_scenes := []
  4. var instances := []
  5.  
  6. var projectiles := []
  7. var index_offsets := []
  8. var test := []
  9.  
  10. var multimeshes := []
  11.  
  12. var is_active := true
  13.  
  14. var time := 0.0
  15.  
  16. func _process(_delta : float) -> void:
  17. # if not Engine.get_idle_frames() % 2 == 0:
  18. # return
  19.  
  20. for i in index_offsets.size():
  21. index_offsets[i] = 0
  22.  
  23. if projectiles.empty():
  24. return
  25.  
  26. for i in projectiles.size():
  27. if projectiles[i].empty():
  28. continue
  29.  
  30. # if not is_active:
  31. # continue
  32.  
  33. for j in projectiles[i].size():
  34. j -= index_offsets[i] # смещение по индексу, нужно после удалении объекта
  35.  
  36. var direct_state_transform : Transform
  37. if projectiles[i][j].physical_body.deleted:
  38. direct_state_transform = projectiles[i][j].physical_body.last_info.transform
  39. else:
  40. var body_rid : RID = projectiles[i][j].physical_body.body_rid
  41. direct_state_transform = PhysicsServer.body_get_direct_state(body_rid).transform
  42.  
  43. var multimesh : MultiMesh = multimeshes[i].multimesh
  44. var offset_transform : Transform = multimeshes[i].get_meta("offset_transform")
  45.  
  46. multimesh.set_instance_transform(j, direct_state_transform * offset_transform)
  47.  
  48. func _physics_process(_delta : float) -> void:
  49. for i in index_offsets.size():
  50. index_offsets[i] = 0
  51.  
  52. if projectiles.empty():
  53. return
  54.  
  55. for i in projectiles.size():
  56. if projectiles[i].empty():
  57. continue
  58.  
  59. for j in projectiles[i].size():
  60. j -= index_offsets[i]
  61.  
  62. # удаление узла по истечению н-ого времени и если это значение больше нуля
  63. if projectiles[i][j].meta_data.life_time > 0 and \
  64. Global.time >= projectiles[i][j].meta_data.init_time + \
  65. projectiles[i][j].meta_data.life_time:
  66. _delete_projectile(i, j)
  67. continue
  68.  
  69. if projectiles[i][j].physical_body.deleted:
  70. continue
  71. else:
  72. projectiles[i][j].physical_body.last_info.transform = projectiles[i][j].physical_body.direct_state.transform
  73.  
  74. var direct_state : PhysicsDirectBodyState = projectiles[i][j].physical_body.direct_state
  75.  
  76. if direct_state.transform.origin.y < -10:
  77. _delete_projectile(i, j)
  78. continue
  79.  
  80. if direct_state.linear_velocity.length() < 0.01:
  81. _delete_physical_body(i, j)
  82. continue
  83.  
  84. var contact_count : int = direct_state.get_contact_count() # получение количество столкновений
  85.  
  86. if contact_count: # произошло столкновение
  87. if projectiles[i][j].meta_data.delete_on_impact:
  88. # удаление физ тела и меша, а после удаление из массива
  89. _delete_projectile(i, j)
  90.  
  91. func projectile(packed_scene : PackedScene, spawn_transform : Transform, \
  92. collision_exceptions := [], _effects := []) -> void:
  93. var instance : Projectile
  94.  
  95. var index := 0
  96. if packed_scenes.empty(): # добавление первого пакета, при отсуствуии коих
  97. _init_packed_scene(packed_scene)
  98. else: # поиск пакетов и получение индекса -1
  99. index = packed_scenes.find(packed_scene)
  100. if packed_scenes[index] != packed_scene: # если данный индекс -1
  101. _init_packed_scene(packed_scene)
  102. # поиск корректного индекса без -1, для последующего использования
  103. index = packed_scenes.find(packed_scenes[index])
  104.  
  105. instance = instances[index]
  106.  
  107. var instance_collision_shape : Shape = instance.get_node("Collision").shape
  108. var shape_form : int
  109. var shape_data := {}
  110. if instance_collision_shape is CapsuleShape:
  111. shape_form = PhysicsServer.SHAPE_CAPSULE
  112. shape_data = {"radius" : instance_collision_shape.radius, \
  113. "height" : instance_collision_shape.height}
  114.  
  115. var rigid_body_data := {
  116. "mass" : instance.mass,
  117. "friction" : instance.physics_material_override.friction,
  118. "bounce" : instance.physics_material_override.bounce,
  119. "gravity_scale" : instance.gravity_scale,
  120. "contacts_reported" : instance.contacts_reported,
  121. "linear_velocity" : instance.linear_velocity,
  122. "linear_damp" : instance.linear_damp,
  123. "angular_velocity" : instance.angular_velocity,
  124. "angular_damp" : instance.angular_damp,
  125. "collision_layer" : instance.collision_layer,
  126. "collision_mask" : instance.collision_mask,}
  127.  
  128. var impulse_data := {}
  129. if instance.random_impulse:
  130. impulse_data = { # рандомизация данные исходя из ограничений экземпляра
  131. "vector" : Vector3(\
  132. rand_range(instance.impulse_vector_random_range_x.x, \
  133. instance.impulse_vector_random_range_x.y), \
  134. rand_range(instance.impulse_vector_random_range_y.x, \
  135. instance.impulse_vector_random_range_y.y), \
  136. rand_range(instance.impulse_vector_random_range_z.x, \
  137. instance.impulse_vector_random_range_z.y)),
  138. "speed" : rand_range(instance.impulse_speed_random_range.x, \
  139. instance.impulse_speed_random_range.y)}
  140. else: # присваение стандартных значений без рандомизации
  141. impulse_data = {
  142. "vector" : instance.impulse_vector,
  143. "speed" : instance.impulse_speed}
  144.  
  145. projectiles[index].append({
  146. "physical_body" : _physical_body(spawn_transform, shape_form, shape_data, \
  147. rigid_body_data, collision_exceptions, impulse_data),
  148. "meta_data" : {
  149. "delete_on_impact" : instance.delete_on_impact,
  150. "init_time" : Global.time,
  151. "life_time" : instance.life_time
  152. }
  153. })
  154.  
  155. is_active = true
  156.  
  157. multimeshes[index].multimesh.instance_count += 1
  158.  
  159. # print(multimeshes[index].multimesh.instance_count)
  160.  
  161. func _init_packed_scene(packed_scene : PackedScene) -> void:
  162. packed_scenes.append(packed_scene) # добавление
  163. var instance := packed_scene.instance()
  164. instances.append(instance)
  165. projectiles.append([]) # создание пустой массива в н-ом индексе
  166. index_offsets.append(0)
  167. test.append(0)
  168.  
  169. var multimesh_name := str(instance.name) + "MultiMesh"
  170. var instance_mesh : MeshInstance = instance.get_node("Mesh")
  171. multimeshes.append(_add_multimesh(multimesh_name, {
  172. "cast_shadow" : instance_mesh.cast_shadow,
  173. "portal_mode" : instance_mesh.portal_mode,
  174. "offset_transform" : instance_mesh.transform,
  175. "mesh" : instance_mesh.mesh,
  176. }))
  177.  
  178. func _physical_body(spawn_transform : Transform, shape_form : int, shape_data : Dictionary, \
  179. rigid_body_data : Dictionary, collision_exceptions : Array, impulse_data : Dictionary) -> Dictionary:
  180. var body_rid := PhysicsServer.body_create()
  181. var shape_rid = PhysicsServer.shape_create(shape_form)
  182.  
  183. PhysicsServer.shape_set_data(shape_rid, shape_data)
  184. PhysicsServer.body_add_shape(body_rid, shape_rid, Transform())
  185.  
  186. PhysicsServer.body_set_collision_layer(body_rid, rigid_body_data.collision_layer)
  187. PhysicsServer.body_set_collision_mask(body_rid, rigid_body_data.collision_mask)
  188.  
  189. if not collision_exceptions.empty():
  190. for index in collision_exceptions:
  191. PhysicsServer.body_add_collision_exception(body_rid, index)
  192.  
  193. PhysicsServer.body_set_mode(body_rid, PhysicsServer.BODY_MODE_RIGID)
  194. PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_MASS, rigid_body_data.mass)
  195. PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_FRICTION, rigid_body_data.friction)
  196. PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_BOUNCE , rigid_body_data.bounce)
  197. PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_GRAVITY_SCALE, rigid_body_data.gravity_scale)
  198.  
  199. PhysicsServer.body_set_max_contacts_reported(body_rid, rigid_body_data.contacts_reported)
  200.  
  201. PhysicsServer.body_set_state(body_rid, PhysicsServer.BODY_STATE_LINEAR_VELOCITY, rigid_body_data.linear_velocity)
  202. PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_LINEAR_DAMP, rigid_body_data.linear_damp)
  203. PhysicsServer.body_set_state(body_rid, PhysicsServer.BODY_STATE_ANGULAR_VELOCITY, rigid_body_data.angular_velocity)
  204. PhysicsServer.body_set_param(body_rid, PhysicsServer.BODY_PARAM_ANGULAR_DAMP, rigid_body_data.angular_damp)
  205.  
  206. PhysicsServer.body_set_state(body_rid, PhysicsServer.BODY_STATE_TRANSFORM, spawn_transform)
  207. PhysicsServer.body_set_state(body_rid, PhysicsServer.BODY_STATE_SLEEPING, true)
  208. PhysicsServer.body_set_state(body_rid, PhysicsServer.BODY_STATE_CAN_SLEEP, true)
  209.  
  210. PhysicsServer.body_apply_central_impulse(body_rid, spawn_transform.basis * impulse_data.vector * impulse_data.speed)
  211.  
  212. PhysicsServer.body_set_space(body_rid, get_world().space)
  213.  
  214. var direct_state := PhysicsServer.body_get_direct_state(body_rid)
  215.  
  216. return {
  217. "body_rid" : body_rid,
  218. "shape_rid" : shape_rid,
  219. "direct_state" : direct_state,
  220. "last_info" : {
  221. "transform" : null,
  222. },
  223. "deleted" : false,
  224. "deleted_bodies" : 0,
  225. }
  226.  
  227. func _add_multimesh(new_name : String, data := {}) -> MultiMeshInstance:
  228. var multimesh_instance : MultiMeshInstance = MultiMeshInstance.new()
  229. multimesh_instance.name = new_name
  230.  
  231. multimesh_instance.cast_shadow = data.cast_shadow
  232. multimesh_instance.portal_mode = data.portal_mode
  233.  
  234. multimesh_instance.set_meta("offset_transform", data.offset_transform)
  235.  
  236. get_parent().add_child(multimesh_instance)
  237. var new_multimesh := MultiMesh.new()
  238. new_multimesh.transform_format = MultiMesh.TRANSFORM_3D
  239. new_multimesh.mesh = data.mesh
  240. multimesh_instance.multimesh = new_multimesh
  241. return multimesh_instance
  242.  
  243. func _delete_projectile(i : int, j : int) -> void:
  244. index_offsets[i] += 1
  245. if not projectiles[i][j].physical_body.deleted:
  246. PhysicsServer.free_rid(projectiles[i][j].physical_body.body_rid)
  247. PhysicsServer.free_rid(projectiles[i][j].physical_body.shape_rid)
  248. multimeshes[i].multimesh.instance_count -= 1
  249. projectiles[i].remove(j)
  250. test[i] -= 1
  251. if test[i] <= projectiles[i].size():
  252. is_active = true
  253.  
  254. func _delete_physical_body(i : int, j : int) -> void:
  255. PhysicsServer.free_rid(projectiles[i][j].physical_body.body_rid)
  256. PhysicsServer.free_rid(projectiles[i][j].physical_body.shape_rid)
  257. projectiles[i][j].physical_body.deleted = true
  258. test[i] += 1
  259. if test[i] >= projectiles[i].size():
  260. is_active = false
  261.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement