Skip to content

Instantly share code, notes, and snippets.

@AAGene
Last active June 27, 2024 09:58
Show Gist options
  • Save AAGene/e42c3c8ce518feb8a27b921e72aafee4 to your computer and use it in GitHub Desktop.
Save AAGene/e42c3c8ce518feb8a27b921e72aafee4 to your computer and use it in GitHub Desktop.
AA mount tutorial

Tutorial: Adding a new Mount in ArcheAge

Note: This tutorial uses a backported model, and does not cover creating & exporting a custom model

Game Files (game_pak)

Model

I'll be using the wyvern model from 3.0. You can source this model on your own.

  • At the root of your game_pak, create a custom folder. In my case, it'll be "genesis"
  • Inside that folder, you'll place your custom files. Make them follow the base structure of the rest of the game_pak, just container in your custom folder.
  • Place the wyvern (or your own) model in the custom folder. It should look like this : game\genesis\objects\characters\animals\wyvern
  • Go in the model folder (wyvern) and edit the following files:
    • wyvern.mtl
    • wyvern.cdf
    • wyvern.cal In both of these files, edit the various paths to match your own. If you use the content root folder as described above, you mostly need to simply add "genesis/" in front of the paths. Paths starting with "game/" should still start with it, just make it "game/genesis/..."

You may also want custom icons for the item, skills etc... Like before, these go in the custom folder.

Animations

The same goes for animations. If you have files in the "animations/graph" folder, you'll have to put them in the base folder of the game, as the animation system does not take a full path.

This should be it for the model side of things. Not much more is needed here.

Database (compact.sqlite3)

I'll go on a table by table basis. Since this is backporting, it's a bit easier, when creating your own, you may have to fiddle with values a bit.

Table: npcs

First, we want to add a new line in npcs to define the NPC itself. The line (in my case) looks like:

INSERT INTO "npcs"
("id", "name", "char_race_id", "npc_grade_id", "npc_kind_id", "level", "npc_template_id", "equip_bodies_id", "equip_cloths_id", "equip_weapons_id", "model_id", "faction_id", "skill_trainer", "ai_file_id", "merchant", "npc_nickname_id", "auctioneer", "show_name_tag", "visible_to_creator_only", "no_exp", "pet_item_id", "base_skill_id", "track_friendship", "priest", "comment1", "npc_tendency_id", "blacksmith", "teleporter", "opacity", "ability_changer", "scale", "comment2", "comment3", "sight_range_scale", "sight_fov_scale", "milestone_id", "attack_start_range_scale", "aggression", "exp_multiplier", "exp_adder", "stabler", "accept_aggro_link", "recruiting_battle_field_id", "return_distance", "npc_ai_param_id", "non_pushable_by_actor", "banker", "aggro_link_special_rule_id", "aggro_link_help_dist", "aggro_link_sight_check", "expedition", "honor_point", "trader", "aggro_link_special_guard", "aggro_link_special_ignore_npc_attacker", "comment_wear", "absolute_return_distance", "repairman", "activate_ai_always", "so_state", "specialty", "sound_pack_id", "specialty_coin_id", "use_range_mod", "npc_posture_set_id", "mate_equip_slot_pack_id", "mate_kind_id", "engage_combat_give_quest_id", "total_custom_id", "no_apply_total_custom", "base_skill_strafe", "base_skill_delay", "npc_interaction_set_id", "use_abuser_list", "return_when_enter_housing_area", "look_converter", "use_ddcms_mount_skill", "crowd_effect", "fx_scale", "translate", "no_penalty", "show_faction_tag", "force_target_me_on_attack")
VALUES (9000001, 'Wyvern', 0, 1, 8, 55, 9, 0, 0, 0, 9000001, 2, 'f', 26, 'f', 0, 'f', 't', 'f', 't', 0, 2, 'f', 'f', '', 0, 'f', 'f', 1.0, 'f', 1.0, '', '', 1.0, 1.0, 0, 1.0, 'f', 1.0, 'f', 'f', 'f', 0, 50.0, 0, 't', 'f', 0, 6.0, 'f', 'f', 0, 'f', 'f', 'f', '', 200, 'f', 'f', '', 'f', 0, 0, 't', 0, 1, 15, 0, 0, 'f', 't', 0.0, 0, 't', 'f', 'f', 't', 't', 1.0, 't', 'f', 'f', 'f');

There isn't a whole lot to say about this. Now you may have noticed a model ID (which I set to 9000001). This in the original DB corresponds to the model ID 2051, but I want to port this over as custom content, so I base my ID off of 9000xxx to ensure no conflicts with existing content (from later patches too)

Table: models

Same here, I'll copy over the model, which gives me this query:

INSERT INTO "models"
("id", "comment", "sub_id", "sub_type", "dying_time", "sound_material_id", "big", "target_decal_size", "use_target_decal", "use_target_silhouette", "use_target_highlight", "name", "camera_distance", "show_name_tag", "name_tag_offset", "sound_pack_id", "despawn_doodad_on_collision", "play_mount_animation", "selectable", "mount_pose_id", "camera_distance_for_wide_angle")
VALUES (9000001, 'Wyvern model - Backport', 9000001, 'ActorModel', 15.0, 1, 't', 1.0, 'f', 't', 'f', 'wyvern', 45.0, 't', 10.0, 526, 'f', 'f', 't', 16, 45.0);

Once again, for sub_id I put in 9000001 which will be added in the actor_models table. The original (3.0) sub_id value is 990 sound_pack_id and mount_pose_id also need to be added as custom IDs - I didn't do it here

If you're making a mount...

Add a line in the model_bindings table. ID: Custom ID, incremental owner_id: your model ID owner_type: Model attach_point_id: 1 horse_rein: f/t depends on you

Table: actor_models

INSERT INTO "main"."actor_models"
("id", "use_ragdoll", "use_ragdoll_hit", "hit_power", "rope_back", "beanstalk_back", "hrope_down", "radius", "height", "model_file", "movement_id", "sight_range", "sight_fov", "shared_dummy_model", "use_random_idle_control", "fly_mode", "underwater_creature", "attack_start_range", "physics_flags", "physics_mass", "physics_stiffness_scale", "physics_living_mass", "physics_living_gravity", "physics_living_air_resistance", "physics_living_k_air_control", "physics_living_max_vel_ground", "physics_living_min_slide_angle", "physics_living_max_climb_angle", "physics_living_min_fall_angle", "physics_living_time_impulse_recover", "physics_living_collider_mat", "game_look_ik_blend_spine1", "game_look_ik_blend_spine2", "game_look_ik_blend_spine3", "game_look_ik_blend_neck", "game_look_ik_blend_head", "game_bow_look_ik_blend_spine1", "game_bow_look_ik_blend_spine2", "game_bow_look_ik_blend_spine3", "game_bow_look_ik_blend_neck", "game_bow_look_ik_blend_head", "game_sprint_multiplier", "game_strafe_multiplier", "game_backward_multiplier", "game_grab_multiplier", "game_walk_multiplier", "game_inertia", "game_inertia_accel", "game_jump_height", "game_lean_shift", "game_lean_angle", "game_max_grab_mass", "game_max_grab_volume", "slope_alignment", "rope_hanging_hand_offset_x", "rope_hanging_hand_offset_y", "rope_hanging_hand_offset_z", "portrait", "use_ragdoll_knock_down", "animation_graph", "upperbody_graph", "turn_speed", "push_ragdoll", "face_target_instantly", "ground_targetable", "swim_height", "actor_height", "hand_rate", "game_walk_strafe_multiplier", "game_walk_backward_multiplier", "game_forward_multiplier", "game_forward_diagonal_multiplier", "game_backward_diagonal_multiplier", "game_walk_forward_diagonal_multiplier", "game_walk_backward_diagonal_multiplier")
VALUES (9000001, 'f', 'f', 10, 0.22, 0.5, 2.2, 8.0, 7.0, 'genesis/objects/Characters/animals/wyvern/wyvern.cdf', 1, 10.0, 180.0, 'f', 't', 'f', 'f', 10.0, 0, 600, 73, 600, 30.0, 0.29, 0.9, 30, 75.0, 80.0, 80.0, 1.0, 'mat_player_collider', 0.05, 0.1, 0.15, 0.0, 0.7, 0.05, 0.15, 0.35, 0.0, 0.7, 1.5, 1.0, 1.0, 1.0, 1.0, 4.0, 11.0, 0.0, 0.35, 15, 70, 2.0, 1, 0.0, 0.0, 2.05, '', 'f', 'wyvern_full_body.xml', '', 360.0, 'f', 'f', 'f', 0.0, 1.8, 0.9, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0);

Notice I put genesis/objects and not objects/ for the model path

Table: game_stances

I won't detail this one, it's fairly simple. Create as many stances as your model needs (8-9 usually), all pointing to your actor_model. In my case I simply ported over the stances for actor_model_id 990, assigning them IDs starting at 9000001

This table is needed for animations to work. If you don't do it, your NPC/mount will look weird.

Bonus section

Creating the item to spawn the mount

Adding a custom Icon (OPTIONAL)

If you want to use a custom icon, you'll need to add the icon (dds format) in game/ui/icon This path cannot be set to a custom one, so try and add a prefix to your custom icons to make them easier to find.

Once it is added in the icon directory, you also need to add a line in database:

INSERT INTO "icons" ("id", "filename", "name")
VALUES (9000001, 'YOUR CUSTOM ICON NAME.dds', 'YOUR ICON NAME (this is more of a comment)');

Creating the item itself

Simply add a line in the items table:

INSERT INTO "items"
("id", "name", "category_id", "level", "description", "price", "refund", "bind_id", "pickup_limit", "max_stack_size", "icon_id", "sellable", "use_skill_id", "use_skill_as_reagent", "impl_id", "pickup_sound_id", "milestone_id", "buff_id", "gradable", "loot_multi", "loot_quest_id", "notify_ui", "use_or_equipment_sound_id", "honor_price", "exp_abs_lifetime", "exp_online_lifetime", "exp_date", "specialty_zone_id", "level_requirement", "comment", "auction_a_category_id", "auction_b_category_id", "auction_c_category_id", "level_limit", "fixed_grade", "disenchantable", "living_point_price", "actability_group_id", "actability_requirement", "grade_enchantable", "char_gender_id", "one_time_sale", "limited_sale_count", "male_icon_id", "over_icon_id", "translate", "auto_register_to_actionbar")
VALUES (9000001, 'Golden Wyvern', 144, 1, 'Golden Wyvern Mount', 50000, 5000, 2, 0, 1, 9000001, 'f', 9000001, 'f', 11, 5681, 0, 0, 'f', 'f', 0, 't', 5680, 0, 0, 0, 0.0, 0, 0, 'comment', 9, 34, 0, 0, 6, 'f', 0, 0, 0, 'f', 0, 'f', 0, 0, 0, 't', 'f');

Do note the skill_id 9000001 also

Once that is added, we're going to need to add a line in item_summon_mates such as this:

INSERT INTO "item_summon_mates" ("id", "item_id", "npc_id")
VALUES (9000001, 9000001, 9000001);

This one is obvious, we only have 9000001 because they're all the first entries.

Finally, we need to add the summoning skill, which is also very simple.

The skill will be spread over 4 tables:

  • skills: Defines the skill itself
  • skill_effects: Binds the summoning effect to the skill
  • effects: Details which implementation of effect to use
  • special_effects: The actual SpawnPet effect

So let's get this done.

Table: skills

INSERT INTO "skills"
("id", "name", "desc", "cost", "icon_id", "show", "start_anim_id", "fire_anim_id", "ability_id", "mana_cost", "timing_id", "weapon_slot_for_autoattack_id", "cooldown_time", "casting_time", "ignore_global_cooldown", "effect_delay", "effect_speed", "effect_repeat_count", "effect_repeat_tick", "category_id", "active_weapon_id", "target_type_id", "target_selection_id", "target_relation_id", "target_area_count", "target_area_radius", "target_siege", "weapon_slot_for_angle_id", "target_angle", "weapon_slot_for_range_id", "min_range", "max_range", "keep_stealth", "stop_autoattack", "aggro", "fx_group_id", "projectile_id", "check_obstacle", "channeling_time", "channeling_tick", "channeling_mana", "channeling_anim_id", "channeling_target_buff_id", "target_area_angle", "ability_level", "channeling_doodad_id", "cooldown_tag_id", "skill_controller_id", "repeat_count", "repeat_tick", "toggle_buff_id", "target_dead", "channeling_buff_id", "reagent_corpse_status_id", "source_dead", "level_step", "valid_height", "target_valid_height", "source_mount", "stop_casting_on_big_hit", "stop_channeling_on_big_hit", "auto_learn", "need_learn", "mainhand_tool_id", "offhand_tool_id", "front_angle", "mana_level_md", "twohand_fire_anim_id", "unmount", "damage_type_id", "allow_to_prisoner", "milestone_id", "match_animation", "plot_id", "use_anim_time", "start_autoattack", "consume_lp", "source_stun", "target_alive", "web_desc", "target_water", "use_skill_camera", "controller_camera", "camera_speed", "controller_camera_speed", "camera_max_distance", "camera_duration", "camera_acceleration", "camera_slow_down_distance", "camera_hold_z", "casting_inc", "casting_cancelable", "casting_delayable", "channeling_cancelable", "target_offset_angle", "target_offset_distance", "actability_group_id", "plot_only", "pitch_angle", "skill_controller_at_end", "end_skill_controller", "string_instrument_start_anim_id", "percussion_instrument_start_anim_id", "tube_instrument_start_anim_id", "string_instrument_fire_anim_id", "percussion_instrument_fire_anim_id", "tube_instrument_fire_anim_id", "or_unit_reqs", "default_gcd", "show_target_casting_time", "valid_height_edge_to_edge", "link_equip_slot_id", "link_backpack_type_id", "keep_mana_regen", "crime_point", "level_rule_no_consideration", "use_weapon_cooldown_time", "synergy_icon1_buffkind", "synergy_icon1_id", "synergy_icon2_buffkind", "synergy_icon2_id", "combat_dice_id", "can_active_weapon_without_anim", "custom_gcd", "cancel_ongoing_buffs", "cancel_ongoing_buff_exception_tag_id", "source_cannot_use_while_walk", "source_mount_mate", "match_animation_count", "dual_wield_fire_anim_id", "auto_fire", "check_terrain", "target_only_water", "source_not_swim", "target_preoccupied", "stop_channeling_on_start_skill", "stop_casting_by_turn", "target_my_npc", "gain_life_point", "target_fishing", "source_no_slave", "auto_reuse", "auto_reuse_delay", "source_not_collided", "skill_points", "doodad_hit_family", "name_tr", "desc_tr", "web_desc_tr", "sensitive_operation", "first_reagent_only", "source_alive", "target_decal_radius", "doodad_bundle_id")
VALUES (9000001, 'Summon Golden Wyvern', 'Summons the Golden Wyvern', 10, 399, 't', 0, 393, 0, 0, 1, 0, 0, 0, 'f', 0, 0.0, 0, 0, 1, 0, 12, 4, 0, 1, 0, 'f', -1, 0, -1, 0, 0, 'f', 'f', 0, 929, 0, 't', 0, 0, 0, 0, 0, 360, 1, 0, 2833, 0, 1, 100, 0, 'f', 0, 0, 'f', 1, 0.0, 0.0, 'f', 'f', 'f', 't', 'f', 0, 0, 0, 0.0, 0, 'f', 0, 'f', 0, 'f', 0, 'f', 'f', 0, 'f', 't', '', 't', 'f', 'f', 20.0, 80, 5.0, 1.0, 0.2, 2.0, 'f', 0, 'f', 'f', 'f', 0.0, 0.0, 0, 'f', 0.0, 'f', 'f', 0, 0, 0, 0, 0, 0, 'f', 't', 't', 't', -1, 1, 't', 0, 'f', 'f', 't', 0, 't', 0, 4, 'f', 0, 't', 0, 'f', 'f', 'f', 0, 'f', 'f', 'f', 'f', 'f', 'f', 'f', 'f', 0, 'f', 'f', 'f', 0, 'f', 1, 0, '', '', '', 'f', 'f', 't', 0, 0);

It's a lot, but you mainly want to touch the name/desc on this one. Maybe the icon too, but that isn't shown.

Table: skill_effects

INSERT INTO "skill_effects"
("id", "skill_id", "effect_id", "weight", "start_level", "end_level", "friendly", "non_friendly", "target_buff_tag_id", "target_nobuff_tag_id", "source_buff_tag_id", "source_nobuff_tag_id", "chance", "front", "back", "target_npc_tag_id", "application_method_id", "synergy_text", "consume_source_item", "consume_item_id", "consume_item_count", "always_hit", "item_set_id", "interaction_success_hit")
VALUES (9000001, 9000001, 9000001, 0, 1, 99, 't', 't', 0, 0, 0, 0, 100, 't', 't', 0, 1, 'f', 'f', 0, 1, 'f', 0, 0);

Here, the first ID is incremental, the second ID is your custom skill's ID, and the third is the effect ID that you'll create next.

Table: effects

INSERT INTO "effects"
("id", "actual_id", "actual_type")
VALUES (9000001, 9000001, 'SpecialEffect');

First ID is your effect ID (used in skill_effects), second is your special_effects ID (defined just after)

Table: special_effects

INSERT INTO "special_effects"
("id", "special_effect_type_id", "value1", "value2", "value3", "value4")
VALUES (9000001, 24, 3466, 0, 0, 0);

The ID is going to be your special_effects ID, 24 is the type "SpawnPet" and 3466 we're not sure what it means just yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment