Last active
January 4, 2022 23:11
-
-
Save kergalym/f09098c03b752d24448a981a32849a3f to your computer and use it in GitHub Desktop.
P3D Archery Code Fragment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
self.arrows = [] | |
self.dropped_arrows = [] | |
self.arrow_brb_in_use = None | |
self.arrow_ref = None | |
self.target_np = None | |
self.arrow_nums_in_inv = 20 | |
self.prepare_arrows(self.bow, "bow_arrow", spine_joint) | |
self.draw_bow_is_done = 0 | |
taskMgr.add(self.cursor_state_task, "cursor_state_task") | |
taskMgr.add(self.arrow_hit_check, "arrow_hit_check") | |
taskMgr.add(self.charge_arrow_task, "charge_arrow_task") | |
taskMgr.add(self.arrow_fly_task, "arrow_fly_task") | |
def draw_bow_anim_state(self, actor, state, loop): | |
if isinstance(state, str) and isinstance(loop, int): | |
self.stateControl = actor.getAnimControl(state) | |
if self.stateControl and not self.stateControl.isPlaying(): | |
if self.draw_bow_is_done == 0: | |
actor.play(state) | |
self.draw_bow_is_done = 1 | |
def cursor_state_task(self, task): | |
if (self.has_weapon['bow'] | |
and not self.key_map["melee_attack"] | |
and self.key_map["archery_attack"]): | |
self.cursor_ui.show() | |
base.camera.set_x(0.5) | |
base.camera.set_y(-2) | |
self.is_aiming = True | |
if (self.has_weapon['bow'] | |
and not self.key_map["melee_attack"] | |
and not self.key_map["archery_attack"] | |
and self.is_aiming): | |
self.cursor_ui.hide() | |
base.camera.set_x(0) | |
base.camera.set_y(self.cam_y_back_pos) | |
self.is_aiming = False | |
return task.cont | |
def prepare_arrows(self, bow, arrow_name, joint): | |
if bow and arrow_name and isinstance(arrow_name, str) and joint: | |
for i in range(self.arrow_nums_in_inv): | |
arrow = base.loader.loadModel('{0}/Assets/Weapons/bow_arrow.egg'.format(self.game_dir)) | |
arrow.set_name(arrow_name) | |
arrow.reparent_to(joint) | |
arrow.set_pos(-10, 7, -12) | |
arrow.set_hpr(91.55, 0, 0) | |
arrow.set_scale(100) | |
arrow.set_python_tag("power", 0) | |
arrow.set_python_tag("ready", 0) | |
arrow.set_python_tag("shot", 0) | |
arrow.set_python_tag("owner", "player") | |
self.arrows.append(arrow) | |
def return_arrow_back(self, joint): | |
if self.arrow_ref and joint: | |
if self.arrow_ref.get_python_tag("ready") == 0: | |
self.arrow_ref.reparent_to(joint) | |
self.arrow_ref.set_pos(-10, 7, -12) | |
self.arrow_ref.set_hpr(91.55, 0, 0) | |
self.arrow_ref.set_scale(100) | |
self.arrow_ref.set_python_tag("power", 0) | |
self.arrow_ref.set_python_tag("ready", 0) | |
self.arrow_ref.set_python_tag("shot", 0) | |
self.arrows.append(self.arrow_ref) | |
if self.arrow_brb_in_use: | |
self.world.remove_rigid_body(self.arrow_brb_in_use.node()) | |
self.arrow_brb_in_use.remove_node() | |
def prepare_arrow_for_shoot(self, bow): | |
if bow: | |
if len(self.arrows) < 1: | |
return | |
# Remove arrow from inv and prepare it for use | |
arrow = self.arrows.pop(0) | |
arrow.reparent_to(bow) | |
arrow.set_pos(0.04, -0.01, -0.01) | |
arrow.set_hpr(0, 2.86, 0) | |
arrow.set_scale(1) | |
# Create arrow collider | |
shape = BulletBoxShape(Vec3(0.05, 0.5, 0.05)) | |
body = BulletRigidBodyNode('Arrow') | |
arrow_rb_np = NodePath(body) | |
arrow_rb_np.wrt_reparent_to(bow) | |
arrow_rb_np.set_pos(arrow.get_pos()) | |
arrow_rb_np.set_hpr(arrow.get_hpr()) | |
arrow_rb_np.set_scale(arrow.get_scale()) | |
arrow.wrt_reparent_to(arrow_rb_np) | |
arrow_rb_np.node().add_shape(shape) | |
arrow_rb_np.node().set_mass(2.0) | |
# Player and its owning arrow won't collide with each other | |
arrow_rb_np.set_collide_mask(BitMask32.bit(0)) | |
# Enable CCD | |
arrow_rb_np.node().set_ccd_motion_threshold(1e-7) | |
arrow_rb_np.node().set_ccd_swept_sphere_radius(0.50) | |
arrow_rb_np.node().set_kinematic(True) | |
self.world.attach_rigid_body(arrow_rb_np.node()) | |
self.arrow_brb_in_use = arrow_rb_np | |
self.arrow_ref = arrow | |
def charge_arrow_task(self, task): | |
if (self.key_map["melee_attack"] | |
and self.key_map["archery_attack"]): | |
if self.arrow_brb_in_use: | |
power = self.arrow_ref.get_python_tag("power") | |
power += 1 | |
self.arrow_ref.set_python_tag("power", power) | |
self.arrow_ref.set_python_tag("ready", 1) | |
if not self.key_map["melee_attack"] and self.key_map["archery_attack"]: | |
if self.arrow_brb_in_use and self.arrow_ref.get_python_tag("ready") == 1: | |
if self.arrow_ref.get_python_tag("shot") == 0: | |
self.bow_shoot() | |
if (not self.key_map["melee_attack"] | |
and not self.key_map["archery_attack"]): | |
if self.draw_bow_is_done == 1: | |
self.draw_bow_is_done = 0 | |
self.korlan.stop("draw_bow") | |
return task.cont | |
def bow_shoot(self): | |
if self.arrow_brb_in_use and self.target_pos and self.hit_target: | |
name = self.hit_target.get_name() | |
self.target_np = render.find("**/{0}".format(name)) | |
self.arrow_ref.set_python_tag("shot", 1) | |
# Get Bullet Rigid Body wrapped arrow | |
self.arrow_brb_in_use.node().set_kinematic(False) | |
self.arrow_brb_in_use.wrt_reparent_to(render) | |
# We record arrows which have been shot | |
self.dropped_arrows.append(self.arrow_brb_in_use) | |
Sequence(Wait(1), Func(self.prepare_arrow_for_shoot, self.bow)).start() | |
# Destroy dropped arrows after 200 seconds which are 3 minutes | |
taskMgr.do_method_later(200, self.destroy_arrow, 'destroy_arrow') | |
def arrow_fly_task(self, task): | |
dt = globalClock.getDt() | |
if self.arrow_brb_in_use: | |
power = self.arrow_ref.get_python_tag("power") | |
if power and self.arrow_ref.get_python_tag("shot") == 1: | |
self.arrow_brb_in_use.set_x(self.arrow_brb_in_use, -power * dt) | |
return task.cont | |
def arrow_hit_check(self, task): | |
if self.arrow_brb_in_use: | |
mouse_watch = base.mouseWatcherNode | |
if mouse_watch.has_mouse(): | |
pos_mouse = base.mouseWatcherNode.get_mouse() | |
pos_from = Point3() | |
pos_to = Point3() | |
base.camLens.extrude(pos_mouse, pos_from, pos_to) | |
pos_from = self.render.get_relative_point(base.camera, pos_from) | |
pos_to = self.render.get_relative_point(base.camera, pos_to) | |
self.raytest_result = self.world.ray_test_closest(pos_from, pos_to) | |
if self.raytest_result.get_node() \ | |
and "Ground" not in str(self.raytest_result.get_node().get_name()) \ | |
and "Korlan" not in str(self.raytest_result.get_node().get_name()): | |
self.hit_target = self.raytest_result.get_node() | |
self.target_pos = self.raytest_result.get_hit_pos() | |
if self.hit_target: | |
self.target_test_ui.setText(self.hit_target.get_name()) | |
else: | |
self.target_test_ui.setText("") | |
if self.arrow_brb_in_use: | |
self.world.contactTest(self.hit_target) | |
if self.world.contactTest(self.hit_target).getNumContacts() > 0: | |
if self.arrow_ref.get_python_tag("ready") == 1: | |
if self.target_np: | |
self.arrow_brb_in_use.wrt_reparent_to(self.target_np) | |
self.reset_arrow_charge() | |
return task.cont | |
def reset_arrow_charge(self): | |
if self.arrow_brb_in_use: | |
self.arrow_ref.set_python_tag("power", 0) | |
def destroy_arrow(self, task): | |
if len(self.arrows) < 1: | |
return | |
if self.dropped_arrows: | |
for arrow_rb in self.dropped_arrows: | |
self.world.removeRigidBody(arrow_rb.node()) | |
arrow_rb.remove_node() | |
return task.done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment