This is code from The Vision related to "chariot". I share it here so anyone can use it and help me to solve my problem with collision detection (the only reason why I don't put it on single player campaign of my mods).
As The Vision is SP only, then my code is, but I think it's not hard to convert it to MP code.
It needs pavise.brf of The Vision to work. The file contains meshes for the cart and it's wheels. The meshes are based on native's cart model. I removed the wheels as separated meshes and repositioned them to simplify the transformation computations.
Edit1 : Adding missing constants (maximum_turn_angle & maximum_forward_range) at module_constants.py
Edit2 : Adding missing constant (delay_for_spawn) at module_mission_templates.py
As The Vision is SP only, then my code is, but I think it's not hard to convert it to MP code.
It needs pavise.brf of The Vision to work. The file contains meshes for the cart and it's wheels. The meshes are based on native's cart model. I removed the wheels as separated meshes and repositioned them to simplify the transformation computations.
Code:
scene_prop_attached_left = 3 # left wheel
scene_prop_attached_right = 4 # right wheel
scene_prop_attached_horse = 5 # horse
scene_prop_rotation = 6 # wheel's angle
scene_prop_destroyed = 7 # status (check if it's destroyed already)
slot_horse_cart = 26 # agent slots to get the cart instance id form the horse
slot_horse_forward = 27 # horse's relative destination (distance and angle)
slot_horse_angle = 28
maximum_turn_angle = 45
maximum_forward_range = 15
Code:
("moving_wheel_left",sokf_moveable,"wheel_left",0,[]),
("moving_wheel_right",sokf_moveable,"wheel_right",0,[]),
# notes : cart_barriers related was my trial to attach dummy scene prop to detect collisions. If anyone has a better idea, please tell me
#("cart_barrier",sokf_moveable,0,"bobo",[]),
("moving_cart",sokf_moveable|sokf_destructible,"moving_cart","bo_moving_cart",
[(ti_on_init_scene_prop,
[(set_fixed_point_multiplier, 100),
(store_trigger_param_1, ":instance_no"),
(prop_instance_get_position, pos1, ":instance_no"),
(set_spawn_position, pos1),
(spawn_scene_prop, "spr_moving_wheel_left"),
(assign, ":wheel_left", reg0),
(spawn_scene_prop, "spr_moving_wheel_right"),
(assign, ":wheel_right", reg0),
#(copy_position, pos3, pos1), (copy_position, pos2, pos1),
#(position_move_x, pos3, 150, 0), (position_move_x, pos2, -150, 0),
#(set_spawn_position, pos3), (spawn_scene_prop, "spr_cart_barrier"),
#(assign, ":phy_right", reg0),
#(set_spawn_position, pos2), (spawn_scene_prop, "spr_cart_barrier"),
#(assign, ":phy_left", reg0),
(scene_prop_set_slot,":instance_no", scene_prop_attached_left, ":wheel_left"),
(scene_prop_set_slot,":instance_no", scene_prop_attached_right, ":wheel_right"),
#(scene_prop_set_slot,":instance_no", scene_prop_phy_left, ":phy_left"),
#(scene_prop_set_slot,":instance_no", scene_prop_phy_right, ":phy_right"),
(scene_prop_set_slot, ":wheel_left", scene_prop_rotation, 0),
(scene_prop_set_slot, ":wheel_right",scene_prop_rotation, 0),
(assign, ":horse", reg1),
(try_begin),
(ge, ":horse", 0),
(position_move_z, pos1, -72,0),
(position_move_y, pos1, 239,0),
(set_spawn_position, pos1),
(spawn_horse, ":horse"),
(scene_prop_set_slot, ":instance_no",scene_prop_attached_horse, reg0),
(agent_set_slot, reg0, slot_horse_cart, ":instance_no"),
(else_try),
(scene_prop_set_slot, ":instance_no",scene_prop_attached_horse, -1),
(try_end),
]),
(ti_on_scene_prop_destroy,
[(store_trigger_param_1, ":instance_no"),
(store_trigger_param_2, ":attacker_agent_no"),
(set_fixed_point_multiplier, 100),
(prop_instance_get_position, pos1, ":instance_no"),
(play_sound_at_position,"snd_dummy_destroyed", pos1),
(assign, ":rotate_side", 86),
(try_begin),
(ge, ":attacker_agent_no", 0),
(agent_get_position, pos2, ":attacker_agent_no"),
(try_begin),
(position_is_behind_position, pos2, pos1),
(val_mul, ":rotate_side", -1),
(try_end),
(try_end),
(init_position, pos3),
(try_begin),
(ge, ":rotate_side", 0),
(position_move_y, pos3, -100),
(else_try),
(position_move_y, pos3, 100),
(try_end),
(position_move_x, pos3, -50),
(position_transform_position_to_parent, pos4, pos1, pos3),
(position_move_z, pos4, 100),
(position_get_distance_to_ground_level, ":height_to_terrain", pos4),
(val_sub, ":height_to_terrain", 100),
(assign, ":z_difference", ":height_to_terrain"),
(val_div, ":z_difference", 3),
(try_begin),
(ge, ":rotate_side", 0),
(val_add, ":rotate_side", ":z_difference"),
(else_try),
(val_sub, ":rotate_side", ":z_difference"),
(try_end),
(position_rotate_x, pos1, ":rotate_side"),
(prop_instance_animate_to_position, ":instance_no", pos1, 70), ]),#animate to position 1 in 0.7 second
(ti_on_scene_prop_hit,
[(play_sound_at_position,"snd_dummy_hit", pos1),
(particle_system_burst, "psys_dummy_smoke", pos1, 3),
(particle_system_burst, "psys_dummy_straw", pos1, 10), ]), ]),
Code:
delay_for_spawn = 0.2
# MST03c. Moving Cart
# Key reading to control
cart_control = (0.1, 0, 0,
[(neg|main_hero_fallen), (ge, "$player_cart", 0), (assign, ":cart_command", 0),
(try_begin),
(key_is_down, "$key_cart_right"), (assign, ":cart_command", 3), # Turn Right
(else_try),
(key_is_down, "$key_cart_left"), (assign, ":cart_command", 4), # Turn Left
(else_try),
(key_is_down, "$key_cart_forward"), (assign, ":cart_command", 1), # Accelerate
(else_try),
(key_is_down, "$key_cart_brake"), (assign, ":cart_command", 2), # Deccelerate
(try_end),
(scene_prop_get_slot, ":horse", "$player_cart", scene_prop_attached_horse),
(call_script, "script_control_cart_horse", ":cart_command", ":horse"),], [])
# Safety, clear the global var first
cart_init = (ti_before_mission_start, 0, 0, [], [(assign, "$player_cart", -1),])
# if player has itm_cart, then deploy it
cart_spawn = (0, delay_for_spawn, ti_once,
[(player_has_item, itm_cart),(call_script, "script_deploy_cart", -1, itm_hunter),], [])
# Scanning
cart_scan = (0.1, 0, 0, [(call_script, "script_cart_scan"),], [])
carts = [cart_init,cart_spawn, cart_control, cart_scan]
Code:
] + carts, ),
Code:
# Deploy the cart. If agent=-1 then use entry point o position that usually is player initial position.
("deploy_cart",
[(store_script_param, ":agent_no", 1),
(store_script_param, ":horse", 2),
(set_fixed_point_multiplier, 100),
(try_begin),
(ge, ":agent_no", 0),
(agent_get_position, pos2, ":agent_no"),
(else_try),
(entry_point_get_position, pos2, 0),
(try_end),
(position_move_y, pos2, 75, 0),
(position_move_z, pos2, 72, 0),
(set_spawn_position, pos2),
(assign, reg1, ":horse"),
(spawn_scene_prop, "spr_moving_cart"), ]),
("cart_scan",
[(set_fixed_point_multiplier, 100),
(get_player_agent_no, ":player_agent"),
(try_begin), # If we have a cart already, check if it's valid
(ge, "$player_cart", 0),
(prop_instance_is_valid, "$player_cart"),
(try_begin), # If we still on it?
(neg|scene_prop_has_agent_on_it, "$player_cart", ":player_agent"),
(assign, "$player_cart", -1),
(try_end),
(else_try),
(assign, "$player_cart", -1),
(try_end),
(scene_prop_get_num_instances, ":num_of_props", "spr_moving_cart"),
(try_for_range, ":props_no", 0, ":num_of_props"), # Multiple Cart? Why not. If only we have good collisions detection among them
(scene_prop_get_instance, ":cart", "spr_moving_cart", ":props_no"),
(try_begin),
(scene_prop_has_agent_on_it, ":cart", ":player_agent"),
(assign, "$player_cart", ":cart"),
(try_end),
(scene_prop_get_slot, ":horse", ":cart", scene_prop_attached_horse), # get the horse
(scene_prop_get_slot, ":wheel_left", ":cart", scene_prop_attached_left), # get the wheels
(scene_prop_get_slot, ":wheel_right", ":cart", scene_prop_attached_right),
#(scene_prop_get_slot, ":phy_right", ":cart", scene_prop_phy_right), # get dummy spr to detect collision (?)
#(scene_prop_get_slot, ":phy_left", ":cart", scene_prop_phy_left),
(try_begin),
(ge, ":horse", 0), # validating the horse is alive
(agent_is_alive, ":horse"),
(prop_instance_get_position, pos5, ":cart"), (agent_get_position, pos2, ":horse"),
#(try_begin),
# (prop_instance_intersects_with_prop_instance, ":phy_right", -1),
# (display_message, "@right"),
# (prop_instance_get_position, pos1, ":wheel_left"),
# (prop_instance_get_position, pos2, ":wheel_right"),
# (prop_instance_get_position, pos3, ":wheel_left"),
# (prop_instance_get_position, pos4, ":phy_right"),
# (position_move_x, pos1, -10), (position_move_x, pos2, -10), (position_move_x, pos3, -10), (position_move_x, pos4, -10), (position_move_x, pos5, -10),
# (prop_instance_set_position, ":wheel_left", pos1),
# (prop_instance_set_position, ":wheel_right", pos2),
# (prop_instance_set_position, ":phy_left", pos3),
# (prop_instance_set_position, ":phy_right", pos4),
# (prop_instance_set_position, ":cart", pos5),
#(else_try),
# (prop_instance_intersects_with_prop_instance, ":phy_left", -1),
# (display_message, "@left"),
# (prop_instance_get_position, pos1, ":wheel_left"),
# (prop_instance_get_position, pos2, ":wheel_right"),
# (prop_instance_get_position, pos3, ":wheel_left"),
# (prop_instance_get_position, pos4, ":phy_right"),
# (position_move_x, pos1, 10), (position_move_x, pos2, 10), (position_move_x, pos3, 10), (position_move_x, pos4, 10), (position_move_x, pos5, 10),
# (prop_instance_set_position, ":wheel_left", pos1),
# (prop_instance_set_position, ":wheel_right", pos2),
# (prop_instance_set_position, ":phy_left", pos3),
# (prop_instance_set_position, ":phy_right", pos4),
# (prop_instance_set_position, ":cart", pos5),
#(try_end),
# terrain adjustments
(position_get_distance_to_terrain, ":horse_level", pos2),
(copy_position, pos3, pos2),
(position_move_y, pos3, -239,0),
(position_move_x, pos3, 100,0),
(position_get_distance_to_terrain, ":right_level", pos3),
(position_move_x, pos3, -200,0),
(position_get_distance_to_terrain, ":left_level", pos3),
(store_add, ":average", ":right_level", ":left_level"),
(val_div, ":average", 2), (val_sub, ":average", ":horse_level"), (val_mul, ":average", 25),
(store_sub, ":different", ":right_level", ":left_level"), (val_mul, ":different", 25),
(copy_position, pos1, pos2),
(position_rotate_x_floating, pos1,":average"),
(position_rotate_y_floating, pos1,":different"),
(position_move_y, pos1, -239,0),
(position_move_z, pos1, 72,0),
(position_get_rotation_around_z, ":speedx", pos1),
(position_get_rotation_around_z, ":angle", pos5),
(val_sub, ":speedx", ":angle"),
(val_clamp, ":speedx", -100, 101),
(agent_get_speed, pos3, ":horse"),
(position_get_y, ":speedy", pos3),
(copy_position, pos2, pos1),
(copy_position, pos4, pos1),
(scene_prop_get_slot, ":rotation_left", ":wheel_left", scene_prop_rotation),
(scene_prop_get_slot, ":rotation_right", ":wheel_right", scene_prop_rotation),
# wheels rotaring adjustments
(try_begin),
(assign, ":stop", 0),
(try_begin),
(eq, ":speedx", 0), (is_between, ":speedy", -20, 21),
(assign, ":stop", 1),
(try_end),
(eq, ":stop", 0),
(val_div, ":speedy", 20),
(val_sub, ":rotation_left", ":speedy"), (val_sub, ":rotation_right", ":speedy"),
(val_add, ":rotation_left", ":speedx"), (val_sub, ":rotation_right", ":speedx"),
(val_mod, ":rotation_left", 36000), (val_mod, ":rotation_right", 36000),
(scene_prop_set_slot, ":wheel_left", scene_prop_rotation, ":rotation_left"),
(scene_prop_set_slot, ":wheel_right", scene_prop_rotation, ":rotation_right"),
(try_end),
(position_rotate_x, pos2, ":rotation_left"), (position_rotate_x, pos4, ":rotation_right"),
#(copy_position, pos3, pos1), (copy_position, pos5, pos1),
#(position_move_x, pos3, 150, 0), (position_move_x, pos5, -150, 0),
# Executing the following the horse animation
(prop_instance_animate_to_position, ":cart", pos1, 12),
#(prop_instance_animate_to_position, ":phy_left", pos5, 12),
#(prop_instance_animate_to_position, ":phy_right", pos3, 12),
(prop_instance_animate_to_position, ":wheel_left", pos2, 12),
(prop_instance_animate_to_position, ":wheel_right", pos4, 12),
(try_end),
(try_end), ]),
("control_cart_horse",
[(store_script_param, ":command", 1),
(store_script_param, ":horse", 2),
(agent_get_slot, ":forward", ":horse", slot_horse_forward),
(agent_get_slot, ":angle", ":horse", slot_horse_angle),
(try_begin),
(eq, ":command", 0),
(val_sub, ":forward", 5),
(assign, ":angle", 0),
(else_try),
(eq, ":command", 1), (val_add, ":forward", 100),
(else_try),
(eq, ":command", 2), (val_sub, ":forward", 100),
(else_try),
(eq, ":command", 3), (val_sub, ":angle", 5),
(else_try),
(eq, ":command", 4), (val_add, ":angle", 5),
(try_end),
(val_clamp, ":forward", 0, maximum_forward_range*100),
(val_clamp, ":angle", -maximum_turn_angle, maximum_turn_angle + 1),
(agent_set_slot, ":horse", slot_horse_forward, ":forward"),
(agent_set_slot, ":horse", slot_horse_angle, ":angle"),
(set_fixed_point_multiplier, 100),
(agent_get_position, pos1, ":horse"),
(position_rotate_z, pos1, ":angle"),
(position_move_y, pos1, ":forward"),
(agent_set_scripted_destination, ":horse", pos1, 1), ]),
Code:
["items_end", "Items End", [("shield_round_a",0)], 0, 0, 1, 0, 0],
# LIMIT VALID ITEM ###############################################################################
# I put it below items_end so it will never be on marketplace, so it should be given to player via script
["cart","Carts", [("cart",0)], itp_type_goods, 0, 410,weight(200)|abundance(1),imodbits_none],
Edit1 : Adding missing constants (maximum_turn_angle & maximum_forward_range) at module_constants.py
Edit2 : Adding missing constant (delay_for_spawn) at module_mission_templates.py