From 0626e90b3aecd6912564740e04ed8d45ef22214f Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sun, 25 Aug 2024 14:51:57 +0200 Subject: [PATCH 01/21] fix some virtual functions, add missing parameters etc. --- src/game_api/entities_activefloors.cpp | 2 +- src/game_api/entities_chars.cpp | 2 +- src/game_api/entities_chars.hpp | 2 +- src/game_api/entity.cpp | 14 ++-- src/game_api/entity.hpp | 36 +++++----- src/game_api/movable.hpp | 71 ++++++++++--------- src/game_api/rpc.cpp | 31 ++++---- src/game_api/rpc.hpp | 4 +- src/game_api/script/lua_vm.cpp | 4 +- src/game_api/script/usertypes/entity_lua.cpp | 26 +++++-- src/game_api/script/usertypes/vtables_lua.cpp | 2 +- src/game_api/sound_manager.hpp | 3 + src/injected/ui.cpp | 32 +++++---- 13 files changed, 129 insertions(+), 100 deletions(-) diff --git a/src/game_api/entities_activefloors.cpp b/src/game_api/entities_activefloors.cpp index 65bf65d92..3888ad922 100644 --- a/src/game_api/entities_activefloors.cpp +++ b/src/game_api/entities_activefloors.cpp @@ -32,7 +32,7 @@ void Drill::trigger(std::optional play_sound_effect) if (overlay != nullptr) { - overlay->remove_item_ptr(this); + overlay->remove_item_ptr(this, true); } move_state = 6; diff --git a/src/game_api/entities_chars.cpp b/src/game_api/entities_chars.cpp index 12e27214d..17b57f344 100644 --- a/src/game_api/entities_chars.cpp +++ b/src/game_api/entities_chars.cpp @@ -140,7 +140,7 @@ void Player::let_go() { if (overlay) { - overlay->remove_item_ptr(this); + overlay->remove_item_ptr(this, true); // coyote_timer = 0xFF; // last_state = state; // state = 1, 9, 0xA; ? diff --git a/src/game_api/entities_chars.hpp b/src/game_api/entities_chars.hpp index 38935fe66..591645fc7 100644 --- a/src/game_api/entities_chars.hpp +++ b/src/game_api/entities_chars.hpp @@ -96,7 +96,7 @@ class PowerupCapable : public Movable int32_t worn_backitem(); // thoes could be wrong becous of the update - virtual void on_blood_collision() = 0; // only triggers when player has kapala + virtual bool on_blood_collision() = 0; // only triggers when player has kapala // called for stunned entities, check bounch of stuff like state, hold entity, standing on entity etc. runs until returned 1 // this is used to clear the last_owner of stunned entity when it is no longed stunned diff --git a/src/game_api/entity.cpp b/src/game_api/entity.cpp index 024974c3e..11d40f7ca 100644 --- a/src/game_api/entity.cpp +++ b/src/game_api/entity.cpp @@ -33,9 +33,9 @@ using namespace std::chrono_literals; void Entity::teleport(float dx, float dy, bool s, float vx, float vy, bool snap) { if (overlay) - overlay->remove_item(uid); - overlay = NULL; - auto topmost = topmost_mount(); + overlay->remove_item(uid, false); + + auto topmost = topmost_mount(); // we just detached from overlay, why do we check this? if (!s) { auto [x_pos, y_pos] = topmost->position(); @@ -78,8 +78,8 @@ void Entity::teleport(float dx, float dy, bool s, float vx, float vy, bool snap) void Entity::teleport_abs(float dx, float dy, float vx, float vy) { if (overlay) - overlay->remove_item(uid); - overlay = NULL; + overlay->remove_item(uid, false); + x = dx; y = dy; if (is_movable()) @@ -178,11 +178,11 @@ Vec2 Entity::position() const return {x_pos, y_pos}; } -void Entity::remove_item(uint32_t item_uid) +void Entity::remove_item(uint32_t item_uid, bool check_autokill) { auto entity = get_entity_ptr(item_uid); if (entity) - remove_item_ptr(entity); + remove_item_ptr(entity, check_autokill); } void Movable::poison(int16_t frames) diff --git a/src/game_api/entity.hpp b/src/game_api/entity.hpp index 7e3954c08..0edc5ce31 100644 --- a/src/game_api/entity.hpp +++ b/src/game_api/entity.hpp @@ -30,6 +30,7 @@ class Movable; struct EntityHooksInfo; using ENT_FLAG = uint32_t; using ENT_MORE_FLAG = uint32_t; +using DAMAGE_TYPE = uint16_t; enum class RECURSIVE_MODE { @@ -192,7 +193,7 @@ class Entity { return Vec2{x, y}; } - void remove_item(uint32_t item_uid); + void remove_item(uint32_t item_uid, bool check_autokill); TEXTURE get_texture() const; /// Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one @@ -261,42 +262,44 @@ class Entity inline static std::function clear_dtor_impl{}; virtual ~Entity() = 0; // vritual 0 - virtual void create_rendering_info() = 0; // 1 + virtual void create_rendering_info() = 0; // 1, potentially also returns the pointer virtual void handle_state_machine() = 0; // 2 /// Kills the entity, you can set responsible to `nil` to ignore it virtual void kill(bool destroy_corpse, Entity* responsible) = 0; // 3 - virtual void on_collision1(Entity* other_entity) = 0; // 4, triggers on collision between whip and hit object + /// Collisions with stuff that blocks you, like walls, floors, etc. Triggers for entities in it's EntityDB.collision_mask + virtual void on_collision1(Entity* other_entity) = 0; // 4 /// Completely removes the entity from existence virtual void destroy() = 0; // 5 - virtual void apply_texture(Texture*) = 0; // 6 - virtual void format_shopitem_name(char16_t*) = 0; // 7 - virtual void generate_stomp_damage_particles(Entity* victim) = 0; // 8, particles when jumping on top of enemy - virtual float get_type_field_a8() = 0; // 9 - virtual bool can_be_pushed() = 0; // 10, (runs only for activefloors?) checks if entity type is pushblock, for chained push block checks ChainedPushBlock.is_chained, is only a check that allows for the pushing animation - virtual bool v11() = 0; // 11, for arrows: returns true if it's moving (for y possibily checks for some speed as well?) + virtual void apply_texture(Texture*) = 0; // 6 + virtual void format_shopitem_name(char16_t*) = 0; // 7 + virtual void generate_stomp_damage_particles(Entity* victim, DAMAGE_TYPE damage, bool) = 0; // 8, particles when jumping on top of enemy + virtual float get_type_field_a8() = 0; // 9 + virtual bool can_be_pushed() = 0; // 10, (runs only for activefloors?) checks if entity type is pushblock, for chained push block checks ChainedPushBlock.is_chained, is only a check that allows for the pushing animation + virtual bool v11() = 0; // 11, for arrows: returns true if it's moving (for y possibly checks for some speed as well?) /// Returns true if entity is in water/lava virtual bool is_in_liquid() = 0; // 12 virtual bool check_type_properties_flags_19() = 0; // 13, checks (properties_flags >> 0x12) & 1; for hermitcrab checks if he's invisible; can't get it to trigger - virtual uint32_t get_type_field_60() = 0; // 14 + virtual uint8_t get_type_field_60() = 0; // 14 virtual void set_invisible(bool value) = 0; // 15 virtual void handle_turning_left(bool apply) = 0; // 16, if disabled, monsters don't turn left and keep walking in the wall (and other right-left issues) - virtual void set_draw_depth(uint8_t draw_depth) = 0; // 17 - virtual void resume_ai() = 0; // 18, works on entities with ai_func != 0; runs when companions are let go from being held. AI resumes anyway in 1.23.3 + virtual void set_draw_depth(uint8_t draw_depth, uint8_t b3f) = 0; // 17 + virtual void resume_ai() = 0; // 18, works on entities with ai_func != 0; runs when companions are let go from being held. AI resumes anyway in 1.23.3, only calls `set_draw_depth` virtual float friction() = 0; // 19 virtual void set_as_sound_source(SoundMeta*) = 0; // 20, update sound position to entity position? - virtual void remove_item_ptr(Entity*) = 0; // 21 + virtual void remove_item_ptr(Entity* entity, bool autokill_check) = 0; // 21, if autokill_check is true, it will check if the entity has the "kill if overlay lost" flag and kill it if it's set virtual Entity* get_held_entity() = 0; // 22 - virtual void v23(Entity* logical_trigger, Entity* who_triggered_it) = 0; // 23, spawns LASERTRAP_SHOT from LASERTRAP, also some trigger entities use this, seam to be called right after "on_collision2", tiggers use self as the first parameter + virtual void v23(Entity* logical_trigger, Entity* who_triggered_it) = 0; // 23, spawns LASERTRAP_SHOT from LASERTRAP, also some trigger entities use this, seam to be called right after "on_collision2", tiggers use self as the first parameter. Called when there is entity overlapping trigger entity, even if they don't move /// Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) virtual bool trigger_action(Entity* user) = 0; // 24 /// Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) virtual void activate(Entity* activator) = 0; // 25 - virtual void on_collision2(Entity* other_entity) = 0; // 26, needs investigating, difference between this and on_collision1, maybe this is on_hitbox_overlap as it works for logical tiggers + /// More like on_overlap, triggers when entities touch/overlap each other. Triggers for entities in it's EntityDB.collision2_mask + virtual void on_collision2(Entity* other_entity) = 0; // 26 /// e.g. for turkey: stores health, poison/curse state, for mattock: remaining swings (returned value is transferred) virtual uint16_t get_metadata() = 0; // 27 @@ -307,7 +310,8 @@ class Entity virtual void on_stood_on_by(Entity* entity) = 0; // 32, e.g. pots, skulls, pushblocks, ... standing on floors virtual void toggle_backlayer_illumination() = 0; // 33, only for CHAR_*: when going to the backlayer, turns on player emitted light virtual void v34() = 0; // 34, only ITEM_TORCH, calls Torch.light_up(false), can't get it to trigger - virtual void liberate_from_shop() = 0; // 35, can also be seen as event: when you anger the shopkeeper, this function gets called for each item; can be called on shopitems individually as well and they become 'purchased' + /// `clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 + virtual void liberate_from_shop(bool clear_parrent) = 0; // 35, can also be seen as event: when you anger the shopkeeper, this function gets called for each item; can be called on shopitems individually as well and they become 'purchased' /// Applies changes made in `entity.type` virtual void apply_db() = 0; // 36, This is actually just an initialize call that is happening once after the entity is created diff --git a/src/game_api/movable.hpp b/src/game_api/movable.hpp index df6706c31..b2d631dcb 100644 --- a/src/game_api/movable.hpp +++ b/src/game_api/movable.hpp @@ -8,7 +8,6 @@ #include struct MovableBehavior; -using DAMAGE_TYPE = uint16_t; class CutsceneBehavior { @@ -159,17 +158,17 @@ class Movable : public Entity /// Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. virtual bool can_jump() = 0; // 37 - virtual void get_collision_info(CollisionInfo* dest) = 0; // 38 - virtual float sprint_factor() = 0; // 39 - virtual void calculate_jump_height() = 0; // 40, when disabled, jump height is very high + virtual void get_collision_info(CollisionInfo& dest) = 0; // 38, from entityDB + virtual float sprint_factor() = 0; // 39, from entityDB + virtual float calculate_jump_velocity() = 0; // 40 virtual std::unordered_map& get_animation_map() = 0; // 41 - virtual void apply_velocity(Vec2* velocities, bool) = 0; // 42, param is pointer to an array of two floats: velocity x and y, could be returninig something + virtual void apply_velocity(Vec2& velocities, bool ignore_weight) = 0; // 42 /// Returns stomp damage based on shoes and fall time virtual int8_t stomp_damage() = 0; // 43, calculates the amount of stomp damage applied (checks spike shoes, movable.state and stand_counter resulting in different damage values) virtual int8_t stomp_damage_trampoline() = 0; // 44, simply jumps to the 43rd virtual function, aka stomp_damage... virtual bool is_on_fire() = 0; // 45 - virtual void v46() = 0; // 46 - virtual void v47() = 0; // 47 + virtual bool v46(Entity*) = 0; // 46, on_melee_attack? called on monsters when you touch them + virtual bool v47(Entity*) = 0; // 47, actual on_thrown_by ? /// Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil. /// Returns: true if entity was affected, damage_dealer should break etc. false if the event should be ignored by damage_dealer? @@ -177,34 +176,36 @@ class Movable : public Entity /// Hit by broken arrows etc that don't deal damage, calls on_damage with 0 damage. virtual void on_hit(Entity* damage_dealer) = 0; // 49 - virtual void v50() = 0; // 50 - virtual void stun(uint16_t framecount) = 0; // 51 - virtual void freeze(uint8_t framecount) = 0; // 52 + /// returns sound id for the damage taken, return 0 to make it silence + virtual uint32_t get_damage_sound(DAMAGE_TYPE damage) = 0; // 50 + virtual void stun(uint16_t framecount) = 0; // 51 + /// Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time + virtual void freeze(uint8_t framecount, bool ignore_lava) = 0; // 52 /// Does not damage entity virtual void light_on_fire(uint8_t time) = 0; // 53 virtual void set_cursed(bool b, bool effect) = 0; // 54 - virtual void on_spiderweb_collision() = 0; // 55 + virtual void on_spiderweb_collision(bool) = 0; // 55, the bool sets pause statemachine flag? needs testing virtual void set_last_owner_uid_b127(Entity* owner) = 0; // 56, assigns player as last_owner_uid and also manipulates movable.b127 virtual uint32_t get_last_owner_uid() = 0; // 57, for players, it checks !stunned && !frozen && !cursed && !has_overlay; for others: just returns last_owner_uid /// Disable to not get killed outside level bounds. - virtual void check_out_of_bounds() = 0; // 58, kills with the 'still falling' death cause, is called for any item/fx/mount/monster/player but not for liquid :( - virtual void v59() = 0; // 59 - virtual Entity* standing_on() = 0; // 60, looks up movable.standing_on_uid in state.instance_id_to_pointer - virtual void on_stomped_on_by(Entity* stomper) = 0; // 61 - virtual void on_thrown_by(Entity* thrower) = 0; // 62, implemented for special cases like hired hand (player with ai_func), horned lizard... - virtual void on_clonegunshot_hit(Entity* clone) = 0; // 63, implemented for player/hired hand: copies health to clone etc - virtual uint32_t get_type_id() = 0; // 64 - virtual bool doesnt_have_spikeshoes() = 0; // 65 - virtual bool is_player_mount_or_monster() = 0; // 66 - virtual void pick_up(Entity* entity_to_pick_up) = 0; // 67 - virtual void on_picked_up_by(Entity* entity_picking_up) = 0; // 68 + virtual void check_out_of_bounds() = 0; // 58, kills with the 'still falling' death cause, is called for any item/fx/mount/monster/player + virtual void set_standing_on(int32_t entity_uid) = 0; // 59 + virtual Entity* standing_on() = 0; // 60, looks up movable.standing_on_uid in state.instance_id_to_pointer + virtual bool on_stomped_on_by(Entity* stomper) = 0; // 61 + virtual void on_thrown_by(Entity* thrower) = 0; // 62, implemented for special cases like hired hand (player with ai_func), horned lizard... + virtual void on_clonegunshot_hit(Entity* clone, int32_t some_entity_uid) = 0; // 63, implemented for player/hired hand: copies health to clone etc + virtual uint32_t get_type_id() = 0; // 64 + virtual bool doesnt_have_spikeshoes() = 0; // 65 + virtual bool is_player_mount_or_monster() = 0; // 66 + virtual void pick_up(Entity* entity_to_pick_up) = 0; // 67 + virtual void on_picked_up_by(Entity* entity_picking_up, bool) = 0; // 68 /// Called when dropping or throwing - virtual void drop(Entity* entity_to_drop) = 0; // 69, also used when throwing + virtual void drop() = 0; // 69 /// Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. - virtual void collect_treasure(int32_t value, ENT_TYPE treasure) = 0; // 70 - virtual void apply_movement() = 0; // 71, disable this function and things can't move, some spin in place + virtual bool collect_treasure(int32_t value, ENT_TYPE treasure) = 0; // 70 + virtual void apply_movement(uint8_t, uint8_t, uint8_t) = 0; // 71, disable this function and things can't move, some spin in place (might have more parameters, the first three probably all bool) virtual void damage_entity(Entity* victim) = 0; // 72, can't trigger, maybe extra params are needed virtual void v73() = 0; // 73 virtual bool is_monster_or_player() = 0; // 74 @@ -217,14 +218,14 @@ class Movable : public Entity virtual void hired_hand_related() = 0; // 81, checks ai_func, gets triggered just after throwing hired hand virtual void generate_fall_poof_particles() = 0; // 82, entity.velocityy must be < -0.12 to generate a poof, might do other stuff regarding falling/landing /// Applies gravity to entity. Disable to float like on hoverpack. - virtual void handle_fall_logic() = 0; // 83, adjusts entity.velocityy when falling - virtual void apply_friction() = 0; // 84, applies entity.type.friction to entity.velocityx - virtual void boss_related() = 0; // 85, when disabled, quillback keeps stomping through the level, including border tiles - virtual void v86() = 0; // 86, triggers when tusk is angered, calls get_last_owner_uid - virtual void gravity_related() = 0; // 87 - virtual void v88() = 0; // 88 - virtual void stack_plus_28_is_0() = 0; // 89, unknown; triggers on item_rubble - virtual void on_crushed_by(Entity*) = 0; // 90, e.g. crushed by elevator, punishball, pushblock, crushtrap (not quillback or boulder) - virtual void on_fall_onto(uint32_t unknown, Entity* fell_on_entity) = 0; // 91 - virtual void on_instakill_death() = 0; // 92, seems to only trigger for enemies that die in one hit + virtual void handle_fall_logic(float) = 0; // 83, adjusts entity.velocityy when falling + virtual void apply_friction(float, bool vertical, float) = 0; // 84, applies entity.type.friction to entity.velocityx, the two floats for characters just multiply the friction, could also be returning the value + virtual bool boss_related(bool) = 0; // 85, when disabled, quillback keeps stomping through the level, including border tiles + virtual void v86(void*, Entity*) = 0; // 86, triggers when tusk is angered, calls get_last_owner_uid + virtual void gravity_related(Entity*, float, Entity*) = 0; // 87 + virtual void v88(Entity*, float) = 0; // 88, calls on_fall_onto, then virtual 14 on the entity in parameter, edits special offset + virtual uint8_t stack_plus_28_is_0() = 0; // 89, unknown; triggers on item_rubble + virtual void on_crushed_by(Entity*) = 0; // 90, e.g. crushed by elevator, punishball, pushblock, crushtrap (not quillback or boulder) + virtual SoundMeta* on_fall_onto(uint32_t play_sound_id, Entity* fell_on_entity) = 0; // 91 + virtual void on_instakill_death() = 0; // 92, seems to only trigger for enemies that die in one hit }; diff --git a/src/game_api/rpc.cpp b/src/game_api/rpc.cpp index caa4df5de..1e49d52d5 100644 --- a/src/game_api/rpc.cpp +++ b/src/game_api/rpc.cpp @@ -69,7 +69,7 @@ void attach_entity(Entity* overlay, Entity* attachee) { if (attachee->overlay) { - overlay->remove_item_ptr(attachee); + attachee->overlay->remove_item_ptr(attachee, false); } auto [x, y] = overlay->position(); @@ -131,10 +131,6 @@ void stack_entities(uint32_t bottom_uid, uint32_t top_uid, const float (&offset) { if (Entity* top = get_entity_ptr(top_uid)) { - if (top->overlay) - { - top->overlay->remove_item_ptr(top); - } attach_entity(bottom, top); top->x = offset[0]; top->y = offset[1]; @@ -342,12 +338,12 @@ void set_contents(uint32_t uid, ENT_TYPE item_entity_type) container->as()->inside = item_entity_type; } -void entity_remove_item(uint32_t uid, uint32_t item_uid) +void entity_remove_item(uint32_t uid, uint32_t item_uid, std::optional check_autokill) { Entity* entity = get_entity_ptr(uid); if (entity == nullptr) return; - entity->remove_item(item_uid); + entity->remove_item(item_uid, check_autokill.value_or(true)); } void lock_door_at(float x, float y) @@ -577,14 +573,25 @@ void pick_up(uint32_t who_uid, uint32_t what_uid) } } -void drop(uint32_t who_uid, uint32_t what_uid) +void drop(uint32_t who_uid, std::optional what_uid) { - Movable* ent = (Movable*)get_entity_ptr(who_uid); - Movable* item = (Movable*)get_entity_ptr(what_uid); - if (ent != nullptr && item != nullptr) + auto ent = get_entity_ptr(who_uid); + if (ent == nullptr) + return; + + if (!ent->is_movable()) // game would probably use the is_player_or_monster function here, since they are the only ones who should be able to hold something + return; + + auto mov = ent->as(); + if (what_uid.has_value()) // should we handle what_uid = -1 the same way? { - ent->drop(item); + auto item = get_entity_ptr(what_uid.value()); + if (item == nullptr) + return; + if (item->overlay != mov && mov->holding_uid == what_uid) + return; } + mov->drop(); } void unequip_backitem(uint32_t who_uid) diff --git a/src/game_api/rpc.hpp b/src/game_api/rpc.hpp index 78001ae71..30809af73 100644 --- a/src/game_api/rpc.hpp +++ b/src/game_api/rpc.hpp @@ -41,7 +41,7 @@ std::vector filter_entities(std::vector entities, std::funct void set_door_target(uint32_t uid, uint8_t w, uint8_t l, uint8_t t); std::tuple get_door_target(uint32_t uid); void set_contents(uint32_t uid, ENT_TYPE item_entity_type); -void entity_remove_item(uint32_t uid, uint32_t item_uid); +void entity_remove_item(uint32_t uid, uint32_t item_uid, std::optional check_autokill); void lock_door_at(float x, float y); void unlock_door_at(float x, float y); uint32_t get_frame_count_main(); @@ -64,7 +64,7 @@ void set_kapala_hud_icon(int8_t icon_index); void set_blood_multiplication(uint32_t default_multiplier, uint32_t vladscape_multiplier); std::vector read_prng(); void pick_up(uint32_t who_uid, uint32_t what_uid); -void drop(uint32_t who_uid, uint32_t what_uid); +void drop(uint32_t who_uid, std::optional what_uid); void unequip_backitem(uint32_t who_uid); int32_t worn_backitem(uint32_t who_uid); void set_olmec_phase_y_level(uint8_t phase, float y); diff --git a/src/game_api/script/lua_vm.cpp b/src/game_api/script/lua_vm.cpp index 19546ddfe..ecf28ecc3 100644 --- a/src/game_api/script/lua_vm.cpp +++ b/src/game_api/script/lua_vm.cpp @@ -1147,7 +1147,7 @@ end lua["get_render_position"] = get_render_position; /// Get velocity `vx, vy` of an entity by uid. Use this, don't use `Entity.velocityx/velocityy` because those are relative to `Entity.overlay`. lua["get_velocity"] = get_velocity; - /// Remove item by uid from entity + /// Remove item by uid from entity. `check_autokill` defaults to true, checks if entity should be killed when missing overlay and kills it if so (can help with avoiding crashes) lua["entity_remove_item"] = entity_remove_item; /// Spawns and attaches ball and chain to `uid`, the initial position of the ball is at the entity position plus `off_x`, `off_y` lua["attach_ball_and_chain"] = attach_ball_and_chain; @@ -1173,7 +1173,7 @@ end lua["kill_entity"] = kill_entity; /// Pick up another entity by uid. Make sure you're not already holding something, or weird stuff will happen. lua["pick_up"] = pick_up; - /// Drop an entity by uid + /// Drop held entity, `what_uid` optional, if set, it will check if entity is holding that entity first before dropping it lua["drop"] = drop; /// Unequips the currently worn backitem lua["unequip_backitem"] = unequip_backitem; diff --git a/src/game_api/script/usertypes/entity_lua.cpp b/src/game_api/script/usertypes/entity_lua.cpp index 5a37bb72f..43645a6d6 100644 --- a/src/game_api/script/usertypes/entity_lua.cpp +++ b/src/game_api/script/usertypes/entity_lua.cpp @@ -239,9 +239,17 @@ void register_usertypes(sol::state& lua) entity_type["overlaps_with"] = overlaps_with; entity_type["get_texture"] = &Entity::get_texture; entity_type["set_texture"] = &Entity::set_texture; - entity_type["set_draw_depth"] = &Entity::set_draw_depth; + + auto set_draw_depth = sol::overload(&Entity::set_draw_depth, [](Entity& ent, uint8_t depth) // for backward compatibility + { ent.set_draw_depth(depth, 0); }); + + entity_type["set_draw_depth"] = set_draw_depth; entity_type["set_enable_turning"] = &Entity::set_enable_turning; - entity_type["liberate_from_shop"] = &Entity::liberate_from_shop; + + auto liberate_from_shop = sol::overload(&Entity::liberate_from_shop, [](Entity& ent) // for backward compatibility) + { ent.liberate_from_shop(true); }); + + entity_type["liberate_from_shop"] = liberate_from_shop; entity_type["get_held_entity"] = &Entity::get_held_entity; entity_type["set_layer"] = &Entity::set_layer; entity_type["apply_layer"] = &Entity::apply_layer; @@ -274,7 +282,7 @@ void register_usertypes(sol::state& lua) static_cast(&Movable::light_on_fire)); auto add_money = sol::overload( static_cast(&Movable::add_money_broken), - static_cast(&Movable::collect_treasure)); + static_cast(&Movable::collect_treasure)); auto movable_type = lua.new_usertype("Movable", sol::base_classes, sol::bases()); movable_type["move"] = &Movable::move; movable_type["movex"] = &Movable::movex; @@ -304,19 +312,23 @@ void register_usertypes(sol::state& lua) /// NoDoc movable_type["airtime"] = &Movable::falling_timer; movable_type["falling_timer"] = &Movable::falling_timer; - movable_type["is_poisoned"] = &Movable::is_poisoned; - movable_type["poison"] = &Movable::poison; movable_type["dark_shadow_timer"] = &Movable::onfire_effect_timer; movable_type["onfire_effect_timer"] = &Movable::onfire_effect_timer; movable_type["exit_invincibility_timer"] = &Movable::exit_invincibility_timer; movable_type["invincibility_frames_timer"] = &Movable::invincibility_frames_timer; movable_type["frozen_timer"] = &Movable::frozen_timer; + movable_type["price"] = &Movable::price; + movable_type["is_poisoned"] = &Movable::is_poisoned; + movable_type["poison"] = &Movable::poison; movable_type["is_button_pressed"] = &Movable::is_button_pressed; movable_type["is_button_held"] = &Movable::is_button_held; movable_type["is_button_released"] = &Movable::is_button_released; - movable_type["price"] = &Movable::price; movable_type["stun"] = &Movable::stun; - movable_type["freeze"] = &Movable::freeze; + + auto freeze = sol::overload(&Movable::freeze, [](Movable& ent, uint8_t frame_count) // for backward compatibility + { ent.freeze(frame_count, false); }); + + movable_type["freeze"] = freeze; movable_type["light_on_fire"] = light_on_fire; movable_type["set_cursed"] = &Movable::set_cursed_fix; movable_type["drop"] = &Movable::drop; diff --git a/src/game_api/script/usertypes/vtables_lua.cpp b/src/game_api/script/usertypes/vtables_lua.cpp index 5cb5f67f7..b6753168a 100644 --- a/src/game_api/script/usertypes/vtables_lua.cpp +++ b/src/game_api/script/usertypes/vtables_lua.cpp @@ -27,7 +27,7 @@ void register_usertypes(sol::state& lua) VTableEntry<"can_be_pushed", 0xa, bool()>, VTableEntry<"is_in_liquid", 0xc, bool()>, VTableEntry<"set_invisible", 0xf, void(bool)>, - VTableEntry<"friction", 0x11, float()>, + VTableEntry<"friction", 0x13, float()>, VTableEntry<"get_held_entity", 0x16, Entity*()>, VTableEntry<"trigger_action", 0x18, void(Entity*)>, VTableEntry<"activate", 0x19, void(Entity*)>, diff --git a/src/game_api/sound_manager.hpp b/src/game_api/sound_manager.hpp index bb59e0ef1..bb947e6db 100644 --- a/src/game_api/sound_manager.hpp +++ b/src/game_api/sound_manager.hpp @@ -260,6 +260,9 @@ struct SoundInfo std::string sound_name; // not 100% sure if it's standard }; +// there is actually base class that consists of up to the left/right channel, used for the sfx +// then normal sounds that you can find in entities, screens itp. have up to the paddings +// finally music in GameManages has the extra bool in BackgroundSound struct SoundMeta { float x; diff --git a/src/injected/ui.cpp b/src/injected/ui.cpp index 0dc393db5..f6deaa78f 100644 --- a/src/injected/ui.cpp +++ b/src/injected/ui.cpp @@ -1654,7 +1654,7 @@ void spawn_entity_over() auto ent = get_entity_ptr(spawned); if (g_dx == 0 && g_dy == 0) { - ent->set_draw_depth(9); + ent->set_draw_depth(9, 0); ent->flags = set_flag(ent->flags, 4); // pass thru objects ent->flags = set_flag(ent->flags, 10); // no gravity ent->flags = clr_flag(ent->flags, 13); // collides walls @@ -1875,8 +1875,7 @@ void toggle_noclip() if (options["noclip"]) { if (player->overlay) - player->overlay->remove_item(player->uid); - player->overlay = NULL; + player->overlay->remove_item(player->uid, false); player->type->max_speed = 0.3f; } else @@ -1916,9 +1915,8 @@ void force_cheats() player->teleport_abs(x + player->movex * 0.3f, y + player->movey * 0.07f, 0, 0); } else - player->overlay->remove_item(player->uid); + player->overlay->remove_item(player->uid, false); } - player->overlay = NULL; player->standing_on_uid = -1; player->flags |= 1U << 9; player->flags &= ~(1U << 10); @@ -7518,12 +7516,16 @@ void render_entity_props(int uid, bool detached = false) ImGui::SameLine(); if (ImGui::Button("Void##VoidEntity")) { - if (entity->overlay && entity->overlay->is_movable()) + if (entity->overlay) { - auto mount = entity->overlay->as(); - if (mount->holding_uid == entity->uid) + auto mount = entity->overlay->as(); // pre casting to movable before checking + if (entity->overlay->is_movable() && mount->holding_uid == entity->uid) { - mount->holding_uid = -1; + mount->drop(); + } + else + { + mount->remove_item_ptr(entity, false); } } entity->overlay = nullptr; @@ -7575,11 +7577,11 @@ void render_entity_props(int uid, bool detached = false) } else if (overlay->is_movable() && overlay->as()->holding_uid == entity->uid) { - overlay->as()->drop(entity); + overlay->as()->drop(); } else { - overlay->remove_item_ptr(entity); + overlay->remove_item_ptr(entity, true); } } render_uid(overlay->uid, "StateAttached"); @@ -7639,7 +7641,7 @@ void render_entity_props(int uid, bool detached = false) { auto holding = get_entity_ptr(movable->holding_uid); if (holding) - movable->drop(holding); + movable->drop(); else movable->holding_uid = -1; } @@ -7741,7 +7743,7 @@ void render_entity_props(int uid, bool detached = false) removed_uid = ent->uid; } if (removed_uid) - entity_pow->remove_item(removed_uid); + entity_pow->remove_item(removed_uid, true); ImGui::SeparatorText("Powerups"); int removed_powerup = 0; for (const auto& [powerup_id, powerup_entity] : entity_pow->powerups) @@ -7822,7 +7824,7 @@ void render_entity_props(int uid, bool detached = false) removed_uid = ent->uid; } if (removed_uid) - entity->remove_item(removed_uid); + entity->remove_item(removed_uid, true); } endmenu(); } @@ -7961,7 +7963,7 @@ void render_entity_props(int uid, bool detached = false) ImGui::DragFloat("Offset Y##EntityOffsetY", &entity->offsety, 0.5f, -10.0, 10.0, "%.3f"); uint8_t draw_depth = entity->draw_depth; if (ImGui::DragScalar("Draw depth##EntityDrawDepth", ImGuiDataType_U8, &draw_depth, 0.2f, &u8_zero, &u8_draw_depth_max)) - entity->set_draw_depth(draw_depth); + entity->set_draw_depth(draw_depth, 0); if (entity->rendering_info) ImGui::DragScalar("Shader##EntityShader", ImGuiDataType_U8, &entity->rendering_info->shader, 0.2f, &u8_zero, &u8_shader_max); ImGui::DragScalar("Animation frame##EntityAnimationFrame", ImGuiDataType_U16, &entity->animation_frame, 0.2f, &u16_zero, &u16_max); From 264b3dee292a8ac9c17e2918705355c044599b4e Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Wed, 11 Sep 2024 21:46:56 +0200 Subject: [PATCH 02/21] look thru entity virtual functions to understand them better, fix some, add missing parameters, make the vtable hooks not require giving the full signature, instead you can point to the function pointer. Fix auto doc (again) --- docs/game_data/spel2.lua | 125 ++++++++++++------ docs/parse_source.py | 118 ++++++++++++----- docs/src/includes/_enums.md | 20 ++- docs/src/includes/_globals.md | 8 +- docs/src/includes/_types.md | 111 ++++++++++------ src/game_api/color.hpp | 2 +- src/game_api/entities_activefloors.cpp | 2 +- src/game_api/entities_activefloors.hpp | 2 +- src/game_api/entities_chars.cpp | 2 +- src/game_api/entities_items.hpp | 55 ++++---- src/game_api/entities_monsters.hpp | 100 +++++++------- src/game_api/entities_mounts.hpp | 24 ++-- src/game_api/entity.cpp | 8 +- src/game_api/entity.hpp | 39 +++--- src/game_api/math.hpp | 4 +- src/game_api/member_function.hpp | 90 +++++++++++++ src/game_api/movable.hpp | 80 +++++------ src/game_api/rpc.cpp | 4 +- src/game_api/script/lua_vm.cpp | 4 +- src/game_api/script/sol_helper.hpp | 22 +-- .../usertypes/entities_monsters_lua.cpp | 2 + src/game_api/script/usertypes/entity_lua.cpp | 7 +- src/game_api/script/usertypes/vtables_lua.cpp | 66 ++++++--- src/game_api/vtable_hook.hpp | 2 +- src/injected/ui.cpp | 12 +- 25 files changed, 582 insertions(+), 327 deletions(-) create mode 100644 src/game_api/member_function.hpp diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index 8c57890d4..c9a979bbb 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -674,11 +674,12 @@ function get_render_position(uid) end ---@param uid integer ---@return number, number function get_velocity(uid) end ----Remove item by uid from entity +---Remove item by uid from entity. `check_autokill` defaults to true, checks if entity should be killed when missing overlay and kills it if so (can help with avoiding crashes) ---@param uid integer ---@param item_uid integer +---@param check_autokill boolean? ---@return nil -function entity_remove_item(uid, item_uid) end +function entity_remove_item(uid, item_uid, check_autokill) end ---Spawns and attaches ball and chain to `uid`, the initial position of the ball is at the entity position plus `off_x`, `off_y` ---@param uid integer ---@param off_x number @@ -736,9 +737,9 @@ function kill_entity(uid, destroy_corpse) end ---@param what_uid integer ---@return nil function pick_up(who_uid, what_uid) end ----Drop an entity by uid +---Drop held entity, `what_uid` optional, if set, it will check if entity is holding that entity first before dropping it ---@param who_uid integer ----@param what_uid integer +---@param what_uid integer? ---@return nil function drop(who_uid, what_uid) end ---Unequips the currently worn backitem @@ -2515,9 +2516,9 @@ function PRNG:random(min, max) end ---@field topmost_mount fun(self): Entity ---@field get_texture fun(self): TEXTURE ---@field set_texture fun(self, texture_id: TEXTURE): boolean @Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one - ---@field set_draw_depth fun(self, draw_depth: integer): nil + ---@field set_draw_depth fun(self, draw_depth: integer, b3f: integer): nil ---@field set_enable_turning fun(self, enabled: boolean): nil - ---@field liberate_from_shop fun(self): nil + ---@field liberate_from_shop fun(self, clear_parrent: boolean): nil @`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 ---@field get_held_entity fun(self): Entity ---@field set_layer fun(self, layer: LAYER): nil @Moves the entity to specified layer, nothing else happens, so this does not emulate a door transition ---@field apply_layer fun(self): nil @Adds the entity to its own layer, to add it to entity lookup tables without waiting for a state update @@ -2535,6 +2536,8 @@ function PRNG:random(min, max) end ---@field is_in_liquid fun(self): boolean @Returns true if entity is in water/lava ---@field is_cursed fun(self): boolean ---@field update fun(self): nil + ---@field flip fun(self, left: boolean): nil + ---@field can_be_pushed fun(self): boolean ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. @@ -2546,34 +2549,52 @@ function PRNG:random(min, max) end ---@field set_post_update_state_machine fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil update_state_machine(Entity self)` ---@field set_pre_kill fun(self, fun: fun(self: Entity, destroy_corpse: boolean, responsible: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool kill(Entity self, boolean destroy_corpse, Entity responsible)`
Virtual function docs:
Kills the entity, you can set responsible to `nil` to ignore it ---@field set_post_kill fun(self, fun: fun(self: Entity, destroy_corpse: boolean, responsible: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil kill(Entity self, boolean destroy_corpse, Entity responsible)`
Virtual function docs:
Kills the entity, you can set responsible to `nil` to ignore it - ---@field set_pre_on_collision1 fun(self, fun: fun(self: Entity, other_entity: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool on_collision1(Entity self, Entity other_entity)` - ---@field set_post_on_collision1 fun(self, fun: fun(self: Entity, other_entity: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil on_collision1(Entity self, Entity other_entity)` + ---@field set_pre_on_collision1 fun(self, fun: fun(self: Entity, other_entity: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool on_collision1(Entity self, Entity other_entity)`
Virtual function docs:
Collisions with stuff that blocks you, like walls, floors, etc. Triggers for entities in it's EntityDB.collision_mask + ---@field set_post_on_collision1 fun(self, fun: fun(self: Entity, other_entity: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil on_collision1(Entity self, Entity other_entity)`
Virtual function docs:
Collisions with stuff that blocks you, like walls, floors, etc. Triggers for entities in it's EntityDB.collision_mask ---@field set_pre_destroy fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool destroy(Entity self)`
Virtual function docs:
Completely removes the entity from existence ---@field set_post_destroy fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil destroy(Entity self)`
Virtual function docs:
Completely removes the entity from existence + ---@field set_pre_generate_stomp_damage_particles fun(self, fun: fun(self: Entity, victim: Entity, damage: DAMAGE_TYPE, boolean: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool generate_stomp_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, boolean)` + ---@field set_post_generate_stomp_damage_particles fun(self, fun: fun(self: Entity, victim: Entity, damage: DAMAGE_TYPE, boolean: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil generate_stomp_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, boolean)` ---@field set_pre_can_be_pushed fun(self, fun: fun(self: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional can_be_pushed(Entity self)` ---@field set_post_can_be_pushed fun(self, fun: fun(self: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil can_be_pushed(Entity self)` ---@field set_pre_is_in_liquid fun(self, fun: fun(self: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional is_in_liquid(Entity self)`
Virtual function docs:
Returns true if entity is in water/lava ---@field set_post_is_in_liquid fun(self, fun: fun(self: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil is_in_liquid(Entity self)`
Virtual function docs:
Returns true if entity is in water/lava ---@field set_pre_set_invisible fun(self, fun: fun(self: Entity, value: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool set_invisible(Entity self, boolean value)` ---@field set_post_set_invisible fun(self, fun: fun(self: Entity, value: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil set_invisible(Entity self, boolean value)` + ---@field set_pre_flip fun(self, fun: fun(self: Entity, left: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool flip(Entity self, boolean left)` + ---@field set_post_flip fun(self, fun: fun(self: Entity, left: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil flip(Entity self, boolean left)` + ---@field set_pre_set_draw_depth fun(self, fun: fun(self: Entity, draw_depth: integer, b3f: integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool set_draw_depth(Entity self, integer draw_depth, integer b3f)` + ---@field set_post_set_draw_depth fun(self, fun: fun(self: Entity, draw_depth: integer, b3f: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil set_draw_depth(Entity self, integer draw_depth, integer b3f)` + ---@field set_pre_reset_draw_depth fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool reset_draw_depth(Entity self)` + ---@field set_post_reset_draw_depth fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil reset_draw_depth(Entity self)` ---@field set_pre_friction fun(self, fun: fun(self: Entity): number?): CallbackId @Hooks before the virtual function.
The callback signature is `optional friction(Entity self)` ---@field set_post_friction fun(self, fun: fun(self: Entity): number?): CallbackId @Hooks after the virtual function.
The callback signature is `nil friction(Entity self)` + ---@field set_pre_set_as_sound_source fun(self, fun: fun(self: Entity, soundmeta: SoundMeta): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool set_as_sound_source(Entity self, SoundMeta soundmeta)` + ---@field set_post_set_as_sound_source fun(self, fun: fun(self: Entity, soundmeta: SoundMeta): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil set_as_sound_source(Entity self, SoundMeta soundmeta)` + ---@field set_pre_remove_item fun(self, fun: fun(self: Entity, entity: Entity, autokill_check: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool remove_item(Entity self, Entity entity, boolean autokill_check)` + ---@field set_post_remove_item fun(self, fun: fun(self: Entity, entity: Entity, autokill_check: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil remove_item(Entity self, Entity entity, boolean autokill_check)` ---@field set_pre_get_held_entity fun(self, fun: fun(self: Entity): Entity?): CallbackId @Hooks before the virtual function.
The callback signature is `optional get_held_entity(Entity self)` ---@field set_post_get_held_entity fun(self, fun: fun(self: Entity): Entity?): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_held_entity(Entity self)` ---@field set_pre_trigger_action fun(self, fun: fun(self: Entity, user: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) ---@field set_post_trigger_action fun(self, fun: fun(self: Entity, user: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) ---@field set_pre_activate fun(self, fun: fun(self: Entity, activator: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool activate(Entity self, Entity activator)`
Virtual function docs:
Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) ---@field set_post_activate fun(self, fun: fun(self: Entity, activator: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil activate(Entity self, Entity activator)`
Virtual function docs:
Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) - ---@field set_pre_on_collision2 fun(self, fun: fun(self: Entity, other_entity: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool on_collision2(Entity self, Entity other_entity)` - ---@field set_post_on_collision2 fun(self, fun: fun(self: Entity, other_entity: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil on_collision2(Entity self, Entity other_entity)` - ---@field set_pre_walked_on fun(self, fun: fun(self: Entity, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool walked_on(Entity self, Entity)` - ---@field set_post_walked_on fun(self, fun: fun(self: Entity, Entity: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil walked_on(Entity self, Entity)` - ---@field set_pre_walked_off fun(self, fun: fun(self: Entity, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool walked_off(Entity self, Entity)` - ---@field set_post_walked_off fun(self, fun: fun(self: Entity, Entity: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil walked_off(Entity self, Entity)` - ---@field set_pre_ledge_grab fun(self, fun: fun(self: Entity, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool ledge_grab(Entity self, Entity)` - ---@field set_post_ledge_grab fun(self, fun: fun(self: Entity, Entity: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil ledge_grab(Entity self, Entity)` - ---@field set_pre_stood_on fun(self, fun: fun(self: Entity, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool stood_on(Entity self, Entity)` - ---@field set_post_stood_on fun(self, fun: fun(self: Entity, Entity: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil stood_on(Entity self, Entity)` + ---@field set_pre_on_collision2 fun(self, fun: fun(self: Entity, other_entity: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool on_collision2(Entity self, Entity other_entity)`
Virtual function docs:
More like on_overlap, triggers when entities touch/overlap each other. Triggers for entities in it's EntityDB.collision2_mask + ---@field set_post_on_collision2 fun(self, fun: fun(self: Entity, other_entity: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil on_collision2(Entity self, Entity other_entity)`
Virtual function docs:
More like on_overlap, triggers when entities touch/overlap each other. Triggers for entities in it's EntityDB.collision2_mask + ---@field set_pre_get_metadata fun(self, fun: fun(self: Entity): integer?): CallbackId @Hooks before the virtual function.
The callback signature is `optional get_metadata(Entity self)`
Virtual function docs:
e.g. for turkey: stores health, poison/curse state, for mattock: remaining swings (returned value is transferred) + ---@field set_post_get_metadata fun(self, fun: fun(self: Entity): integer?): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_metadata(Entity self)`
Virtual function docs:
e.g. for turkey: stores health, poison/curse state, for mattock: remaining swings (returned value is transferred) + ---@field set_pre_apply_metadata fun(self, fun: fun(self: Entity, metadata: integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool apply_metadata(Entity self, integer metadata)` + ---@field set_post_apply_metadata fun(self, fun: fun(self: Entity, metadata: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil apply_metadata(Entity self, integer metadata)` + ---@field set_pre_walked_on fun(self, fun: fun(self: Entity, walker: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool walked_on(Entity self, Entity walker)` + ---@field set_post_walked_on fun(self, fun: fun(self: Entity, walker: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil walked_on(Entity self, Entity walker)` + ---@field set_pre_walked_off fun(self, fun: fun(self: Entity, walker: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool walked_off(Entity self, Entity walker)` + ---@field set_post_walked_off fun(self, fun: fun(self: Entity, walker: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil walked_off(Entity self, Entity walker)` + ---@field set_pre_ledge_grab fun(self, fun: fun(self: Entity, who: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool ledge_grab(Entity self, Entity who)` + ---@field set_post_ledge_grab fun(self, fun: fun(self: Entity, who: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil ledge_grab(Entity self, Entity who)` + ---@field set_pre_stood_on fun(self, fun: fun(self: Entity, Vec2: Entity entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool stood_on(Entity self, Entity entity Vec2)` + ---@field set_post_stood_on fun(self, fun: fun(self: Entity, Vec2: Entity entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil stood_on(Entity self, Entity entity Vec2)` + ---@field set_pre_liberate_from_shop fun(self, fun: fun(self: Entity, clear_parrent: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool liberate_from_shop(Entity self, boolean clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 + ---@field set_post_liberate_from_shop fun(self, fun: fun(self: Entity, clear_parrent: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil liberate_from_shop(Entity self, boolean clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 ---@field set_pre_init fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool init(Entity self)` ---@field set_post_init fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil init(Entity self)` local Entity = nil @@ -2643,27 +2664,28 @@ function Entity:destroy_recursive() end ---@field wet_effect_timer integer ---@field poison_tick_timer integer @Used to apply damage from poison, can be set to -1 to cure poison, to set poison use [poison_entity](#poison_entity) ---@field falling_timer integer - ---@field is_poisoned fun(self): boolean ---@field dark_shadow_timer integer ---@field onfire_effect_timer integer ---@field exit_invincibility_timer integer ---@field invincibility_frames_timer integer ---@field frozen_timer integer + ---@field price integer + ---@field is_poisoned fun(self): boolean ---@field is_button_pressed fun(self, button: BUTTON): boolean ---@field is_button_held fun(self, button: BUTTON): boolean ---@field is_button_released fun(self, button: BUTTON): boolean - ---@field price integer ---@field stun fun(self, framecount: integer): nil - ---@field freeze fun(self, framecount: integer): nil + ---@field freeze fun(self, framecount: integer, ignore_lava: boolean): nil @Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time ---@field light_on_fire fun(self, time: integer): nil @Does not damage entity ---@field set_cursed fun(self, b: boolean, effect: boolean?): nil @effect = true - plays the sound and spawn particle above entity - ---@field drop fun(self, entity_to_drop: Entity): nil @Called when dropping or throwing + ---@field drop fun(self): nil @Called when dropping or throwing ---@field pick_up fun(self, entity_to_pick_up: Entity): nil - ---@field can_jump fun(self): boolean @Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. ---@field standing_on fun(self): Entity - ---@field collect_treasure fun(self, value: integer, treasure: ENT_TYPE): nil @Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. + ---@field collect_treasure fun(self, value: integer, treasure: ENT_TYPE): boolean @Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. + ---@field can_jump fun(self): boolean @Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. ---@field is_on_fire fun(self): boolean - ---@field damage fun(self, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean @Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected, damage_dealer should break etc. false if the event should be ignored by damage_dealer? + ---@field is_powerup_capable fun(self): boolean + ---@field damage fun(self, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean @Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer ---@field get_all_behaviors fun(self): integer[] @Get all avaible behavior ids ---@field set_behavior fun(self, behavior_id: integer): boolean @Set behavior, this is more than just state as it's an active function, for example climbing ladder is a behavior and it doesn't actually need ladder/rope entity
Returns false if entity doesn't have this behavior id ---@field get_behavior fun(self): integer @Get the current behavior id @@ -2682,26 +2704,40 @@ function Entity:destroy_recursive() end ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. ---@field set_pre_can_jump fun(self, fun: fun(self: Movable): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional can_jump(Movable self)`
Virtual function docs:
Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. ---@field set_post_can_jump fun(self, fun: fun(self: Movable): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil can_jump(Movable self)`
Virtual function docs:
Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. - ---@field set_pre_stomp_damage fun(self, fun: fun(self: Movable): integer?): CallbackId @Hooks before the virtual function.
The callback signature is `optional stomp_damage(Movable self)` - ---@field set_post_stomp_damage fun(self, fun: fun(self: Movable): integer?): CallbackId @Hooks after the virtual function.
The callback signature is `nil stomp_damage(Movable self)` + ---@field set_pre_get_collision_info fun(self, fun: fun(self: Movable, dest: CollisionInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool get_collision_info(Movable self, CollisionInfo dest)` + ---@field set_post_get_collision_info fun(self, fun: fun(self: Movable, dest: CollisionInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_collision_info(Movable self, CollisionInfo dest)` + ---@field set_pre_sprint_factor fun(self, fun: fun(self: Movable): number?): CallbackId @Hooks before the virtual function.
The callback signature is `optional sprint_factor(Movable self)` + ---@field set_post_sprint_factor fun(self, fun: fun(self: Movable): number?): CallbackId @Hooks after the virtual function.
The callback signature is `nil sprint_factor(Movable self)` + ---@field set_pre_calculate_jump_velocity fun(self, fun: fun(self: Movable, dont_ignore_liquid: boolean): number?): CallbackId @Hooks before the virtual function.
The callback signature is `optional calculate_jump_velocity(Movable self, boolean dont_ignore_liquid)` + ---@field set_post_calculate_jump_velocity fun(self, fun: fun(self: Movable, dont_ignore_liquid: boolean): number?): CallbackId @Hooks after the virtual function.
The callback signature is `nil calculate_jump_velocity(Movable self, boolean dont_ignore_liquid)` + ---@field set_pre_get_animation_map fun(self, fun: fun(self: Movable): table): CallbackId @Hooks before the virtual function.
The callback signature is `optional> get_animation_map(Movable self)` + ---@field set_post_get_animation_map fun(self, fun: fun(self: Movable): table): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_animation_map(Movable self)` + ---@field set_pre_apply_velocity fun(self, fun: fun(self: Movable, velocities: Vec2, ignore_weight: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool apply_velocity(Movable self, Vec2 velocities, boolean ignore_weight)` + ---@field set_post_apply_velocity fun(self, fun: fun(self: Movable, velocities: Vec2, ignore_weight: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil apply_velocity(Movable self, Vec2 velocities, boolean ignore_weight)` + ---@field set_pre_get_damage fun(self, fun: fun(self: Movable): integer?): CallbackId @Hooks before the virtual function.
The callback signature is `optional get_damage(Movable self)`
Virtual function docs:
Returns the damage that the entity deals + ---@field set_post_get_damage fun(self, fun: fun(self: Movable): integer?): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_damage(Movable self)`
Virtual function docs:
Returns the damage that the entity deals ---@field set_pre_is_on_fire fun(self, fun: fun(self: Movable): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional is_on_fire(Movable self)` ---@field set_post_is_on_fire fun(self, fun: fun(self: Movable): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil is_on_fire(Movable self)` - ---@field set_pre_damage fun(self, fun: fun(self: Movable, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional damage(Movable self, Entity damage_dealer, integer damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, integer unknown_damage_phase, integer stun_amount, integer iframes, boolean unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected, damage_dealer should break etc. false if the event should be ignored by damage_dealer? - ---@field set_post_damage fun(self, fun: fun(self: Movable, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, integer damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, integer unknown_damage_phase, integer stun_amount, integer iframes, boolean unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected, damage_dealer should break etc. false if the event should be ignored by damage_dealer? - ---@field set_pre_on_hit fun(self, fun: fun(self: Movable, damage_dealer: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls on_damage with 0 damage. - ---@field set_post_on_hit fun(self, fun: fun(self: Movable, damage_dealer: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls on_damage with 0 damage. + ---@field set_pre_damage fun(self, fun: fun(self: Movable, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional damage(Movable self, Entity damage_dealer, integer damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, integer unknown_damage_phase, integer stun_amount, integer iframes, boolean unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer + ---@field set_post_damage fun(self, fun: fun(self: Movable, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, integer damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, integer unknown_damage_phase, integer stun_amount, integer iframes, boolean unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer + ---@field set_pre_on_hit fun(self, fun: fun(self: Movable, damage_dealer: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. + ---@field set_post_on_hit fun(self, fun: fun(self: Movable, damage_dealer: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. + ---@field set_pre_get_damage_sound fun(self, fun: fun(self: Movable, damage: DAMAGE_TYPE): integer?): CallbackId @Hooks before the virtual function.
The callback signature is `optional get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence + ---@field set_post_get_damage_sound fun(self, fun: fun(self: Movable, damage: DAMAGE_TYPE): integer?): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence ---@field set_pre_stun fun(self, fun: fun(self: Movable, framecount: integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool stun(Movable self, integer framecount)` ---@field set_post_stun fun(self, fun: fun(self: Movable, framecount: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil stun(Movable self, integer framecount)` - ---@field set_pre_freeze fun(self, fun: fun(self: Movable, framecount: integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool freeze(Movable self, integer framecount)` - ---@field set_post_freeze fun(self, fun: fun(self: Movable, framecount: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil freeze(Movable self, integer framecount)` + ---@field set_pre_freeze fun(self, fun: fun(self: Movable, framecount: integer, ignore_lava: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool freeze(Movable self, integer framecount, boolean ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time + ---@field set_post_freeze fun(self, fun: fun(self: Movable, framecount: integer, ignore_lava: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil freeze(Movable self, integer framecount, boolean ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time ---@field set_pre_light_on_fire fun(self, fun: fun(self: Movable, time: integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool light_on_fire(Movable self, integer time)`
Virtual function docs:
Does not damage entity ---@field set_post_light_on_fire fun(self, fun: fun(self: Movable, time: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil light_on_fire(Movable self, integer time)`
Virtual function docs:
Does not damage entity ---@field set_pre_set_cursed fun(self, fun: fun(self: Movable, b: boolean, effect: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool set_cursed(Movable self, boolean b, boolean effect)` ---@field set_post_set_cursed fun(self, fun: fun(self: Movable, b: boolean, effect: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil set_cursed(Movable self, boolean b, boolean effect)` ---@field set_pre_web_collision fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool web_collision(Movable self)` ---@field set_post_web_collision fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil web_collision(Movable self)` - ---@field set_pre_check_out_of_bounds fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool check_out_of_bounds(Movable self)` - ---@field set_post_check_out_of_bounds fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil check_out_of_bounds(Movable self)` + ---@field set_pre_check_out_of_bounds fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool check_out_of_bounds(Movable self)`
Virtual function docs:
Disable to not get killed outside level bounds. + ---@field set_post_check_out_of_bounds fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil check_out_of_bounds(Movable self)`
Virtual function docs:
Disable to not get killed outside level bounds. + ---@field set_pre_set_standing_on fun(self, fun: fun(self: Movable, entity_uid: integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool set_standing_on(Movable self, integer entity_uid)` + ---@field set_post_set_standing_on fun(self, fun: fun(self: Movable, entity_uid: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil set_standing_on(Movable self, integer entity_uid)` ---@field set_pre_standing_on fun(self, fun: fun(self: Movable): Entity?): CallbackId @Hooks before the virtual function.
The callback signature is `optional standing_on(Movable self)` ---@field set_post_standing_on fun(self, fun: fun(self: Movable): Entity?): CallbackId @Hooks after the virtual function.
The callback signature is `nil standing_on(Movable self)` ---@field set_pre_stomped_by fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool stomped_by(Movable self, Entity)` @@ -2714,10 +2750,10 @@ function Entity:destroy_recursive() end ---@field set_post_pick_up fun(self, fun: fun(self: Movable, entity_to_pick_up: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil pick_up(Movable self, Entity entity_to_pick_up)` ---@field set_pre_picked_up_by fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool picked_up_by(Movable self, Entity)` ---@field set_post_picked_up_by fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil picked_up_by(Movable self, Entity)` - ---@field set_pre_drop fun(self, fun: fun(self: Movable, entity_to_drop: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool drop(Movable self, Entity entity_to_drop)`
Virtual function docs:
Called when dropping or throwing - ---@field set_post_drop fun(self, fun: fun(self: Movable, entity_to_drop: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil drop(Movable self, Entity entity_to_drop)`
Virtual function docs:
Called when dropping or throwing - ---@field set_pre_collect_treasure fun(self, fun: fun(self: Movable, value: integer, treasure: ENT_TYPE): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool collect_treasure(Movable self, integer value, ENT_TYPE treasure)`
Virtual function docs:
Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. - ---@field set_post_collect_treasure fun(self, fun: fun(self: Movable, value: integer, treasure: ENT_TYPE): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil collect_treasure(Movable self, integer value, ENT_TYPE treasure)`
Virtual function docs:
Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. + ---@field set_pre_drop fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool drop(Movable self)`
Virtual function docs:
Called when dropping or throwing + ---@field set_post_drop fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil drop(Movable self)`
Virtual function docs:
Called when dropping or throwing + ---@field set_pre_collect_treasure fun(self, fun: fun(self: Movable, value: integer, treasure: ENT_TYPE): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional collect_treasure(Movable self, integer value, ENT_TYPE treasure)`
Virtual function docs:
Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. + ---@field set_post_collect_treasure fun(self, fun: fun(self: Movable, value: integer, treasure: ENT_TYPE): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil collect_treasure(Movable self, integer value, ENT_TYPE treasure)`
Virtual function docs:
Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. ---@field set_pre_initialize fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool initialize(Movable self)` ---@field set_post_initialize fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil initialize(Movable self)` ---@field set_pre_process_input fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool process_input(Movable self)` @@ -2726,8 +2762,8 @@ function Entity:destroy_recursive() end ---@field set_post_picked_up fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil picked_up(Movable self)` ---@field set_pre_fall fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool fall(Movable self)` ---@field set_post_fall fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil fall(Movable self)` - ---@field set_pre_apply_friction fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool apply_friction(Movable self)` - ---@field set_post_apply_friction fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil apply_friction(Movable self)` + ---@field set_pre_apply_friction fun(self, fun: fun(self: Movable, number: , vertical: boolean, number: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool apply_friction(Movable self, number, boolean vertical, number)` + ---@field set_post_apply_friction fun(self, fun: fun(self: Movable, number: , vertical: boolean, number: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil apply_friction(Movable self, number, boolean vertical, number)` ---@field set_pre_crush fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool crush(Movable self, Entity)` ---@field set_post_crush fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil crush(Movable self, Entity)` local Movable = nil @@ -3310,6 +3346,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field target_in_sight_timer integer ---@field gold integer @amount of gold he picked up, will be drooped on death ---@field timer_after_humping integer + ---@field collected_treasure ENT_TYPE[] ---@class Crocman : WalkingMonster ---@field teleport_cooldown integer @@ -3719,7 +3756,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@class DummyPurchasableEntity : Purchasable ---@class Bow : Purchasable - ---@field get_arrow_special_offset fun(self): number + ---@field get_arrow_special_offset fun(self): number @When lain on the ground ---@class Present : Purchasable ---@field inside ENT_TYPE @@ -6724,6 +6761,10 @@ function Color:new(color) end ---@param a_ number ---@return Color function Color:new(r_, g_, b_, a_) end +---Create a color from an array of 4 floats +---@param (c number +---@return Color +function Color:new((c) end ---@param color_name string ---@param alpha integer? ---@return Color diff --git a/docs/parse_source.py b/docs/parse_source.py index cc8698c76..f7605b1d9 100644 --- a/docs/parse_source.py +++ b/docs/parse_source.py @@ -43,8 +43,8 @@ "game_unordered_map<": "map<", "game_set<": "set<", "game_unordered_set<": "set<", - "unordered_map<": "map<", # doesn't seam to matter for lua if it's ordered or not - "unordered_set<": "set<", # doesn't seam to matter for lua if it's ordered or not + "unordered_map<": "map<", # doesn't seam to matter for lua if it's ordered or not + "unordered_set<": "set<", # doesn't seam to matter for lua if it's ordered or not # removers ", identity_hasher<>": "", "std::": "", @@ -215,23 +215,25 @@ def cb_signature_dict(ret, param): "param": param, } + def custom_split(var): result = [] level = 0 current = "" for char in var: - if char == ',' and level == 0: + if char == "," and level == 0: result.append(current.strip()) current = "" else: current += char - if char == '[' or char == '(' or char == '<': + if char == "[" or char == "(" or char == "<": level += 1 - elif char == ']' or char == ')' or char == '>': + elif char == "]" or char == ")" or char == ">": level -= 1 result.append(current.strip()) return result + def get_cb_signature(text): signature_ms = reSignature.findall(text) if not signature_ms: @@ -249,9 +251,10 @@ def camel_case_to_snake_case(name): def fix_spaces(thing): thing = thing.strip() - thing = re.sub(r"\s{2,}", " ", thing) # change double spaces into single - thing = re.sub(r"(?<=\(|\<)\s", "", thing) # remove spaces after ( or < - return thing.replace("*", "").replace("&", "") # remove * and & + thing = re.sub(r"\s{2,}", " ", thing) # change double spaces into single + thing = re.sub(r"(?<=\(|\<)\s", "", thing) # remove spaces after ( or < + return thing.replace("*", "").replace("&", "") # remove * and & + def getfunc(name): for func in funcs: @@ -267,9 +270,11 @@ def rpcfunc(name): ret.append(func) return ret + def replace_fun(text): return fix_spaces(replace_fun_import(text)) + def configure_parse(replace_function, cache_file): global replace_fun_import, CACHE_FILE replace_fun_import = replace_function @@ -384,25 +389,27 @@ def run_parse(): if m: continue - m = re.search(r"\s*(virtual\s)?(.*)\s+([^\(]*)\(([^\)]*)", line) + m = re.search( + r"\s*(?:virtual\s)?(.*)\s+([\w]+)\(([^\)]*)", line + ) if m: - name = m[3] + name = m[2] # move ctor is useless for Lua is_move_ctr = ( - re.fullmatch(r"^[a-zA-Z0-9_]*$", name) - and re.fullmatch(rf"\s*{name}\s*&&[^,]*", m[4]) - and not m[2] + re.fullmatch(r"^[\w]*$", name) + and re.fullmatch(rf"\s*{name}\s*&&[^,]*", m[3]) + and not m[1] ) if not is_move_ctr: if name not in member_funs: member_funs[name] = [] - param = m[4] + param = m[3] if " " not in param: param = f"{param} {param.lower()}" member_funs[name].append( { - "return": replace_fun(m[2]), - "name": m[3], + "return": replace_fun(m[1]), + "name": m[2], "param": replace_fun(param), "comment": comment, } @@ -440,7 +447,11 @@ def run_parse(): ) else: member_vars.append( - {"type": replace_fun(m[1]), "name": m[2], "comment": comment} + { + "type": replace_fun(m[1]), + "name": m[2], + "comment": comment, + } ) comment = [] elif brackets_depth == 0: @@ -568,6 +579,7 @@ def run_parse(): data = open(file, "r").read().split("\n") vtables = {} vtable_name = None + skip = False for line in data: if vtable_def := re.search( r'static (\w*) \w*\(lua, lua\["(.*)"\](, "(.*)")?\)', line @@ -592,7 +604,13 @@ def run_parse(): vtable_name = line.split()[1] vtable_entries = {} elif vtable_name != None: + if entry_math := re.search(r"/// NoDoc", line): + skip = True + continue if entry_math := re.search(r"VTableEntry<(.*)>", line): + if skip: + skip = False + continue [name, index, signature_and_binder] = entry_math.group(1).split( ",", 2 ) @@ -606,20 +624,42 @@ def run_parse(): signature = re.sub( r"\), BackBinder<([^>]*)>", r", \g<1>)", signature_and_binder ).replace("(, ", "(") - signature = re.search( - r"([_a-zA-Z][_a-zA-Z0-9]*.*)\((.*)\)", signature - ) - ret = signature.group(1) - args = [ - t for t in signature.group(2).split(",") - ] - vtable_entries[name] = { - "name": name, - "index": index, - "ret": ret, - "args": args, - "binds": binds, - } + func_ref = re.search(r"MemFun<&?([\w]+)::([\w]+)>", line) + + if func_ref and func_ref.group(1) is not None: + for item in classes: + if item["name"] != func_ref.group(1): + continue + # TODO: pretty sure if the actual virtual function name is different then the one in VTableEntry there won't be comment in callback signature + func_name = func_ref.group(2) + # if it throws error at `item["member_funs"][func_name]` then the virtual defined using MemFun was not found in the parsed class/struct code + if ( + item["member_funs"] + and item["member_funs"][func_name] + and len(item["member_funs"][func_name]) > 0 + ): + func = item["member_funs"][func_name][-1] + vtable_entries[name] = { + "name": name, + "index": index, + "ret": func["return"], + "args": [t for t in func["param"].split(",")], + # "ref": func_name.group(2), + "binds": binds, + } + else: + signature = re.search( + r"([_a-zA-Z][\w]*.*)\((.*)\)", signature + ) + ret = signature.group(1) + args = [t for t in signature.group(2).split(",")] + vtable_entries[name] = { + "name": name, + "index": index, + "ret": ret, + "args": args, + "binds": binds, + } if ">>;" in line: vtables[vtable_name] = { "name": vtable_name, @@ -711,7 +751,9 @@ def run_parse(): var[1] = var[1][:-1] var_name = var[0] - cpp = replace_fun(var[1]) # should probably be done later, so the regex doesn't have to relay on some of the changes, also generate_emmylua.py uses some unique formats replacements + cpp = replace_fun( + var[1] + ) # should probably be done later, so the regex doesn't have to relay on some of the changes, also generate_emmylua.py uses some unique formats replacements if var[1].startswith("sol::property"): param_match = re.match( @@ -731,7 +773,7 @@ def run_parse(): cpp_name = cpp else: cpp_name = cpp[cpp.find("::") + 2 :] if cpp.find("::") >= 0 else cpp - + if var_name.startswith("sol::constructors"): for fun in underlying_cpp_type["member_funs"][cpp_type]: param = fun["param"] @@ -746,14 +788,18 @@ def run_parse(): } ) elif cpp.startswith("[]("): - param_match = re.match(r"\[\]\(([\w &*:,]+)?\) -> ([\w.*&<>\?\[\]:]+)?(?: )?{", cpp) + param_match = re.match( + r"\[\]\(([\w &*:,]+)?\) -> ([\w.*&<>\?\[\]:]+)?(?: )?{", cpp + ) if param_match: ret = param_match.group(2) if ret is None: ret = "nil" - + sig = param_match.group(1) - if sig.startswith(cpp_type): # remove the self parameter if present + if sig.startswith( + cpp_type + ): # remove the self parameter if present first_param_end = sig.find(",") + 1 if first_param_end == 0: sig = "" diff --git a/docs/src/includes/_enums.md b/docs/src/includes/_enums.md index c814abaf5..586f6e63a 100644 --- a/docs/src/includes/_enums.md +++ b/docs/src/includes/_enums.md @@ -232,30 +232,46 @@ Name | Data | Description [KILL](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.KILL) | 3 | [ON_COLLISION1](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ON_COLLISION1) | 4 | [DESTROY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.DESTROY) | 5 | +[GENERATE_STOMP_DAMAGE_PARTICLES](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GENERATE_STOMP_DAMAGE_PARTICLES) | 8 | [CAN_BE_PUSHED](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CAN_BE_PUSHED) | 10 | [IS_IN_LIQUID](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.IS_IN_LIQUID) | 12 | [SET_INVISIBLE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.SET_INVISIBLE) | 15 | -[FRICTION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.FRICTION) | 17 | +[FLIP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.FLIP) | 16 | +[SET_DRAW_DEPTH](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.SET_DRAW_DEPTH) | 17 | +[RESET_DRAW_DEPTH](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.RESET_DRAW_DEPTH) | 18 | +[FRICTION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.FRICTION) | 19 | +[SET_AS_SOUND_SOURCE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.SET_AS_SOUND_SOURCE) | 20 | +[REMOVE_ITEM](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.REMOVE_ITEM) | 21 | [GET_HELD_ENTITY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GET_HELD_ENTITY) | 22 | [TRIGGER_ACTION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.TRIGGER_ACTION) | 24 | [ACTIVATE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ACTIVATE) | 25 | [ON_COLLISION2](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ON_COLLISION2) | 26 | +[GET_METADATA](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GET_METADATA) | 27 | +[APPLY_METADATA](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.APPLY_METADATA) | 28 | [WALKED_ON](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.WALKED_ON) | 29 | [WALKED_OFF](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.WALKED_OFF) | 30 | [LEDGE_GRAB](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.LEDGE_GRAB) | 31 | [STOOD_ON](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.STOOD_ON) | 32 | +[LIBERATE_FROM_SHOP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.LIBERATE_FROM_SHOP) | 35 | [INIT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.INIT) | 36 | [CAN_JUMP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CAN_JUMP) | 37 | -[STOMP_DAMAGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.STOMP_DAMAGE) | 43 | +[GET_COLLISION_INFO](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GET_COLLISION_INFO) | 38 | +[SPRINT_FACTOR](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.SPRINT_FACTOR) | 39 | +[CALCULATE_JUMP_VELOCITY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CALCULATE_JUMP_VELOCITY) | 40 | +[GET_ANIMATION_MAP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GET_ANIMATION_MAP) | 41 | +[APPLY_VELOCITY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.APPLY_VELOCITY) | 42 | +[GET_DAMAGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GET_DAMAGE) | 43 | [IS_ON_FIRE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.IS_ON_FIRE) | 45 | [DAMAGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.DAMAGE) | 48 | [ON_HIT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ON_HIT) | 49 | +[GET_DAMAGE_SOUND](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GET_DAMAGE_SOUND) | 50 | [STUN](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.STUN) | 51 | [FREEZE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.FREEZE) | 52 | [LIGHT_ON_FIRE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.LIGHT_ON_FIRE) | 53 | [SET_CURSED](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.SET_CURSED) | 54 | [WEB_COLLISION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.WEB_COLLISION) | 55 | [CHECK_OUT_OF_BOUNDS](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CHECK_OUT_OF_BOUNDS) | 58 | +[SET_STANDING_ON](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.SET_STANDING_ON) | 59 | [STANDING_ON](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.STANDING_ON) | 60 | [STOMPED_BY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.STOMPED_BY) | 61 | [THROWN_BY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.THROWN_BY) | 62 | diff --git a/docs/src/includes/_globals.md b/docs/src/includes/_globals.md index 56c0f4265..d409f6681 100644 --- a/docs/src/includes/_globals.md +++ b/docs/src/includes/_globals.md @@ -523,9 +523,9 @@ Use empty table as argument to reset to the game default > Search script examples for [drop](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=drop) -#### nil drop(int who_uid, int what_uid) +#### nil drop(int who_uid, optional what_uid) -Drop an entity by uid +Drop held entity, `what_uid` optional, if set, it will check if entity is holding that entity first before dropping it ### enter_door @@ -572,9 +572,9 @@ Check if the entity `uid` has some specific `item_uid` by uid in their inventory > Search script examples for [entity_remove_item](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=entity_remove_item) -#### nil entity_remove_item(int uid, int item_uid) +#### nil entity_remove_item(int uid, int item_uid, optional check_autokill) -Remove item by uid from entity +Remove item by uid from entity. `check_autokill` defaults to true, checks if entity should be killed when missing overlay and kills it if so (can help with avoiding crashes) ### filter_entities diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index ebdf84372..22a811152 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -630,6 +630,7 @@ Type | Name | Description [Color](#Color) | [new(Color other)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=Color) | [Color](#Color) | [new(Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=Color) | [Color](#Color) | [new(float r_, float g_, float b_, float a_)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=Color) | Create a new color by specifying its values +[Color](#Color) | [new(float (c)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=Color) | Create a color from an array of 4 floats [Color](#Color) | [new(string color_name, optional alpha = nullopt)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=Color) | float | [r](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=r) | float | [g](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=g) | @@ -4231,9 +4232,9 @@ bool | [overlaps_with(float rect_left, float rect_bottom, float rect_right, floa bool | [overlaps_with(Entity other)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=overlaps_with) | [TEXTURE](#TEXTURE) | [get_texture()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_texture) | bool | [set_texture(TEXTURE texture_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_texture) | Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one -nil | [set_draw_depth(int draw_depth)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_draw_depth) | +nil | [set_draw_depth(int draw_depth, int b3f)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_draw_depth) | nil | [set_enable_turning(bool enabled)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_enable_turning) | -nil | [liberate_from_shop()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=liberate_from_shop) | +nil | [liberate_from_shop(bool clear_parrent)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=liberate_from_shop) | `clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 [Entity](#Entity) | [get_held_entity()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_held_entity) | nil | [set_layer(LAYER layer)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_layer) | Moves the entity to specified layer, nothing else happens, so this does not emulate a door transition nil | [apply_layer()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apply_layer) | Adds the entity to its own layer, to add it to entity lookup tables without waiting for a state update @@ -4255,6 +4256,8 @@ nil | [kill_recursive(bool destroy_corpse, Entity responsible)](https://github.c nil | [destroy_recursive(optional mask, array ent_types, RECURSIVE_MODE rec_mode)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destroy_recursive) | Destroy entity along with all entities attached to it. Be aware that for example destroying push block with this function will also destroy anything on top of it, any items, players, monsters etc.
To avoid that, you can inclusively or exclusively limit certain [MASK](#MASK) and [ENT_TYPE](#ENT_TYPE). Note: the function will first check the mask, if the entity doesn't match, it will look in the provided [ENT_TYPE](#ENT_TYPE)'s nil | [destroy_recursive()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destroy_recursive) | Short for using [RECURSIVE_MODE](#RECURSIVE_MODE).NONE nil | [update()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=update) | +nil | [flip(bool left)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=flip) | +bool | [can_be_pushed()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=can_be_pushed) | [CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. [CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. @@ -4266,34 +4269,52 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_update_state_machine(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_update_state_machine) | Hooks after the virtual function.
The callback signature is `nil update_state_machine(Entity self)` [CallbackId](#Aliases) | [set_pre_kill(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_kill) | Hooks before the virtual function.
The callback signature is `bool kill(Entity self, bool destroy_corpse, Entity responsible)`
Virtual function docs:
Kills the entity, you can set responsible to `nil` to ignore it [CallbackId](#Aliases) | [set_post_kill(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_kill) | Hooks after the virtual function.
The callback signature is `nil kill(Entity self, bool destroy_corpse, Entity responsible)`
Virtual function docs:
Kills the entity, you can set responsible to `nil` to ignore it -[CallbackId](#Aliases) | [set_pre_on_collision1(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_on_collision1) | Hooks before the virtual function.
The callback signature is `bool on_collision1(Entity self, Entity other_entity)` -[CallbackId](#Aliases) | [set_post_on_collision1(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_on_collision1) | Hooks after the virtual function.
The callback signature is `nil on_collision1(Entity self, Entity other_entity)` +[CallbackId](#Aliases) | [set_pre_on_collision1(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_on_collision1) | Hooks before the virtual function.
The callback signature is `bool on_collision1(Entity self, Entity other_entity)`
Virtual function docs:
Collisions with stuff that blocks you, like walls, floors, etc. Triggers for entities in it's EntityDB.collision_mask +[CallbackId](#Aliases) | [set_post_on_collision1(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_on_collision1) | Hooks after the virtual function.
The callback signature is `nil on_collision1(Entity self, Entity other_entity)`
Virtual function docs:
Collisions with stuff that blocks you, like walls, floors, etc. Triggers for entities in it's EntityDB.collision_mask [CallbackId](#Aliases) | [set_pre_destroy(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_destroy) | Hooks before the virtual function.
The callback signature is `bool destroy(Entity self)`
Virtual function docs:
Completely removes the entity from existence [CallbackId](#Aliases) | [set_post_destroy(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_destroy) | Hooks after the virtual function.
The callback signature is `nil destroy(Entity self)`
Virtual function docs:
Completely removes the entity from existence +[CallbackId](#Aliases) | [set_pre_generate_stomp_damage_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_generate_stomp_damage_particles) | Hooks before the virtual function.
The callback signature is `bool generate_stomp_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, bool)` +[CallbackId](#Aliases) | [set_post_generate_stomp_damage_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_generate_stomp_damage_particles) | Hooks after the virtual function.
The callback signature is `nil generate_stomp_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, bool)` [CallbackId](#Aliases) | [set_pre_can_be_pushed(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_can_be_pushed) | Hooks before the virtual function.
The callback signature is `optional can_be_pushed(Entity self)` [CallbackId](#Aliases) | [set_post_can_be_pushed(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_can_be_pushed) | Hooks after the virtual function.
The callback signature is `nil can_be_pushed(Entity self)` [CallbackId](#Aliases) | [set_pre_is_in_liquid(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_is_in_liquid) | Hooks before the virtual function.
The callback signature is `optional is_in_liquid(Entity self)`
Virtual function docs:
Returns true if entity is in water/lava [CallbackId](#Aliases) | [set_post_is_in_liquid(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_is_in_liquid) | Hooks after the virtual function.
The callback signature is `nil is_in_liquid(Entity self)`
Virtual function docs:
Returns true if entity is in water/lava [CallbackId](#Aliases) | [set_pre_set_invisible(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_set_invisible) | Hooks before the virtual function.
The callback signature is `bool set_invisible(Entity self, bool value)` [CallbackId](#Aliases) | [set_post_set_invisible(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_set_invisible) | Hooks after the virtual function.
The callback signature is `nil set_invisible(Entity self, bool value)` +[CallbackId](#Aliases) | [set_pre_flip(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_flip) | Hooks before the virtual function.
The callback signature is `bool flip(Entity self, bool left)` +[CallbackId](#Aliases) | [set_post_flip(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_flip) | Hooks after the virtual function.
The callback signature is `nil flip(Entity self, bool left)` +[CallbackId](#Aliases) | [set_pre_set_draw_depth(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_set_draw_depth) | Hooks before the virtual function.
The callback signature is `bool set_draw_depth(Entity self, int draw_depth, int b3f)` +[CallbackId](#Aliases) | [set_post_set_draw_depth(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_set_draw_depth) | Hooks after the virtual function.
The callback signature is `nil set_draw_depth(Entity self, int draw_depth, int b3f)` +[CallbackId](#Aliases) | [set_pre_reset_draw_depth(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_reset_draw_depth) | Hooks before the virtual function.
The callback signature is `bool reset_draw_depth(Entity self)` +[CallbackId](#Aliases) | [set_post_reset_draw_depth(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_reset_draw_depth) | Hooks after the virtual function.
The callback signature is `nil reset_draw_depth(Entity self)` [CallbackId](#Aliases) | [set_pre_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_friction) | Hooks before the virtual function.
The callback signature is `optional friction(Entity self)` [CallbackId](#Aliases) | [set_post_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_friction) | Hooks after the virtual function.
The callback signature is `nil friction(Entity self)` +[CallbackId](#Aliases) | [set_pre_set_as_sound_source(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_set_as_sound_source) | Hooks before the virtual function.
The callback signature is `bool set_as_sound_source(Entity self, SoundMeta soundmeta)` +[CallbackId](#Aliases) | [set_post_set_as_sound_source(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_set_as_sound_source) | Hooks after the virtual function.
The callback signature is `nil set_as_sound_source(Entity self, SoundMeta soundmeta)` +[CallbackId](#Aliases) | [set_pre_remove_item(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_remove_item) | Hooks before the virtual function.
The callback signature is `bool remove_item(Entity self, Entity entity, bool autokill_check)` +[CallbackId](#Aliases) | [set_post_remove_item(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_remove_item) | Hooks after the virtual function.
The callback signature is `nil remove_item(Entity self, Entity entity, bool autokill_check)` [CallbackId](#Aliases) | [set_pre_get_held_entity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_held_entity) | Hooks before the virtual function.
The callback signature is `optional get_held_entity(Entity self)` [CallbackId](#Aliases) | [set_post_get_held_entity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_held_entity) | Hooks after the virtual function.
The callback signature is `nil get_held_entity(Entity self)` [CallbackId](#Aliases) | [set_pre_trigger_action(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_trigger_action) | Hooks before the virtual function.
The callback signature is `optional trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) [CallbackId](#Aliases) | [set_post_trigger_action(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_trigger_action) | Hooks after the virtual function.
The callback signature is `nil trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) [CallbackId](#Aliases) | [set_pre_activate(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_activate) | Hooks before the virtual function.
The callback signature is `bool activate(Entity self, Entity activator)`
Virtual function docs:
Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) [CallbackId](#Aliases) | [set_post_activate(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_activate) | Hooks after the virtual function.
The callback signature is `nil activate(Entity self, Entity activator)`
Virtual function docs:
Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) -[CallbackId](#Aliases) | [set_pre_on_collision2(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_on_collision2) | Hooks before the virtual function.
The callback signature is `bool on_collision2(Entity self, Entity other_entity)` -[CallbackId](#Aliases) | [set_post_on_collision2(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_on_collision2) | Hooks after the virtual function.
The callback signature is `nil on_collision2(Entity self, Entity other_entity)` -[CallbackId](#Aliases) | [set_pre_walked_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_walked_on) | Hooks before the virtual function.
The callback signature is `bool walked_on(Entity self, Entity)` -[CallbackId](#Aliases) | [set_post_walked_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_walked_on) | Hooks after the virtual function.
The callback signature is `nil walked_on(Entity self, Entity)` -[CallbackId](#Aliases) | [set_pre_walked_off(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_walked_off) | Hooks before the virtual function.
The callback signature is `bool walked_off(Entity self, Entity)` -[CallbackId](#Aliases) | [set_post_walked_off(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_walked_off) | Hooks after the virtual function.
The callback signature is `nil walked_off(Entity self, Entity)` -[CallbackId](#Aliases) | [set_pre_ledge_grab(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_ledge_grab) | Hooks before the virtual function.
The callback signature is `bool ledge_grab(Entity self, Entity)` -[CallbackId](#Aliases) | [set_post_ledge_grab(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_ledge_grab) | Hooks after the virtual function.
The callback signature is `nil ledge_grab(Entity self, Entity)` -[CallbackId](#Aliases) | [set_pre_stood_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stood_on) | Hooks before the virtual function.
The callback signature is `bool stood_on(Entity self, Entity)` -[CallbackId](#Aliases) | [set_post_stood_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stood_on) | Hooks after the virtual function.
The callback signature is `nil stood_on(Entity self, Entity)` +[CallbackId](#Aliases) | [set_pre_on_collision2(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_on_collision2) | Hooks before the virtual function.
The callback signature is `bool on_collision2(Entity self, Entity other_entity)`
Virtual function docs:
More like on_overlap, triggers when entities touch/overlap each other. Triggers for entities in it's EntityDB.collision2_mask +[CallbackId](#Aliases) | [set_post_on_collision2(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_on_collision2) | Hooks after the virtual function.
The callback signature is `nil on_collision2(Entity self, Entity other_entity)`
Virtual function docs:
More like on_overlap, triggers when entities touch/overlap each other. Triggers for entities in it's EntityDB.collision2_mask +[CallbackId](#Aliases) | [set_pre_get_metadata(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_metadata) | Hooks before the virtual function.
The callback signature is `optional get_metadata(Entity self)`
Virtual function docs:
e.g. for turkey: stores health, poison/curse state, for mattock: remaining swings (returned value is transferred) +[CallbackId](#Aliases) | [set_post_get_metadata(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_metadata) | Hooks after the virtual function.
The callback signature is `nil get_metadata(Entity self)`
Virtual function docs:
e.g. for turkey: stores health, poison/curse state, for mattock: remaining swings (returned value is transferred) +[CallbackId](#Aliases) | [set_pre_apply_metadata(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_apply_metadata) | Hooks before the virtual function.
The callback signature is `bool apply_metadata(Entity self, int metadata)` +[CallbackId](#Aliases) | [set_post_apply_metadata(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_apply_metadata) | Hooks after the virtual function.
The callback signature is `nil apply_metadata(Entity self, int metadata)` +[CallbackId](#Aliases) | [set_pre_walked_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_walked_on) | Hooks before the virtual function.
The callback signature is `bool walked_on(Entity self, Entity walker)` +[CallbackId](#Aliases) | [set_post_walked_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_walked_on) | Hooks after the virtual function.
The callback signature is `nil walked_on(Entity self, Entity walker)` +[CallbackId](#Aliases) | [set_pre_walked_off(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_walked_off) | Hooks before the virtual function.
The callback signature is `bool walked_off(Entity self, Entity walker)` +[CallbackId](#Aliases) | [set_post_walked_off(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_walked_off) | Hooks after the virtual function.
The callback signature is `nil walked_off(Entity self, Entity walker)` +[CallbackId](#Aliases) | [set_pre_ledge_grab(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_ledge_grab) | Hooks before the virtual function.
The callback signature is `bool ledge_grab(Entity self, Entity who)` +[CallbackId](#Aliases) | [set_post_ledge_grab(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_ledge_grab) | Hooks after the virtual function.
The callback signature is `nil ledge_grab(Entity self, Entity who)` +[CallbackId](#Aliases) | [set_pre_stood_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stood_on) | Hooks before the virtual function.
The callback signature is `bool stood_on(Entity self, Entity entity Vec2)` +[CallbackId](#Aliases) | [set_post_stood_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stood_on) | Hooks after the virtual function.
The callback signature is `nil stood_on(Entity self, Entity entity Vec2)` +[CallbackId](#Aliases) | [set_pre_liberate_from_shop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_liberate_from_shop) | Hooks before the virtual function.
The callback signature is `bool liberate_from_shop(Entity self, bool clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 +[CallbackId](#Aliases) | [set_post_liberate_from_shop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_liberate_from_shop) | Hooks after the virtual function.
The callback signature is `nil liberate_from_shop(Entity self, bool clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 [CallbackId](#Aliases) | [set_pre_init(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_init) | Hooks before the virtual function.
The callback signature is `bool init(Entity self)` [CallbackId](#Aliases) | [set_post_init(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_init) | Hooks after the virtual function.
The callback signature is `nil init(Entity self)` @@ -5204,6 +5225,7 @@ int | [hump_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=hump int | [target_in_sight_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=target_in_sight_timer) | int | [gold](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=gold) | amount of gold he picked up, will be drooped on death int | [timer_after_humping](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer_after_humping) | +vector<[ENT_TYPE](#ENT_TYPE)> | [collected_treasure](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collected_treasure) | ### MagmaMan @@ -5929,7 +5951,7 @@ Derived from [Entity](#Entity) [Movable](#Movable) [Purchasable](#Purchasable) Type | Name | Description ---- | ---- | ----------- -float | [get_arrow_special_offset()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_arrow_special_offset) | +float | [get_arrow_special_offset()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_arrow_special_offset) | When lain on the ground ### Bullet @@ -6882,27 +6904,28 @@ int | [lock_input_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua& int | [wet_effect_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=wet_effect_timer) | int | [poison_tick_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=poison_tick_timer) | Used to apply damage from poison, can be set to -1 to cure poison, to set poison use [poison_entity](#poison_entity) int | [falling_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=falling_timer) | -bool | [is_poisoned()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_poisoned) | int | [dark_shadow_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=dark_shadow_timer) | int | [onfire_effect_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=onfire_effect_timer) | int | [exit_invincibility_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=exit_invincibility_timer) | int | [invincibility_frames_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=invincibility_frames_timer) | int | [frozen_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=frozen_timer) | +int | [price](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=price) | +bool | [is_poisoned()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_poisoned) | bool | [is_button_pressed(BUTTON button)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_button_pressed) | bool | [is_button_held(BUTTON button)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_button_held) | bool | [is_button_released(BUTTON button)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_button_released) | -int | [price](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=price) | nil | [stun(int framecount)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=stun) | -nil | [freeze(int framecount)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=freeze) | +nil | [freeze(int framecount, bool ignore_lava)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=freeze) | Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time nil | [light_on_fire(int time)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=light_on_fire) | Does not damage entity nil | [set_cursed(bool b, optional effect)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_cursed) | effect = true - plays the sound and spawn particle above entity -nil | [drop(Entity entity_to_drop)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=drop) | Called when dropping or throwing +nil | [drop()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=drop) | Called when dropping or throwing nil | [pick_up(Entity entity_to_pick_up)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=pick_up) | -bool | [can_jump()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=can_jump) | Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. [Entity](#Entity) | [standing_on()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=standing_on) | -nil | [collect_treasure(int value, ENT_TYPE treasure)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collect_treasure) | Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. +bool | [collect_treasure(int value, ENT_TYPE treasure)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collect_treasure) | Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. +bool | [can_jump()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=can_jump) | Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. bool | [is_on_fire()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_on_fire) | -bool | [damage(Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=damage) | Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected, damage_dealer should break etc. false if the event should be ignored by damage_dealer? +bool | [is_powerup_capable()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_powerup_capable) | +bool | [damage(Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=damage) | Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer vector<int> | [get_all_behaviors()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_all_behaviors) | Get all avaible behavior ids bool | [set_behavior(int behavior_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_behavior) | Set behavior, this is more than just state as it's an active function, for example climbing ladder is a behavior and it doesn't actually need ladder/rope entity
Returns false if entity doesn't have this behavior id int | [get_behavior()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_behavior) | Get the current behavior id @@ -6924,26 +6947,40 @@ nil | [generic_update_world(Vec2 move, float sprint_factor, bool disable_gravity nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. [CallbackId](#Aliases) | [set_pre_can_jump(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_can_jump) | Hooks before the virtual function.
The callback signature is `optional can_jump(Movable self)`
Virtual function docs:
Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. [CallbackId](#Aliases) | [set_post_can_jump(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_can_jump) | Hooks after the virtual function.
The callback signature is `nil can_jump(Movable self)`
Virtual function docs:
Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. -[CallbackId](#Aliases) | [set_pre_stomp_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stomp_damage) | Hooks before the virtual function.
The callback signature is `optional stomp_damage(Movable self)` -[CallbackId](#Aliases) | [set_post_stomp_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stomp_damage) | Hooks after the virtual function.
The callback signature is `nil stomp_damage(Movable self)` +[CallbackId](#Aliases) | [set_pre_get_collision_info(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_collision_info) | Hooks before the virtual function.
The callback signature is `bool get_collision_info(Movable self, CollisionInfo dest)` +[CallbackId](#Aliases) | [set_post_get_collision_info(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_collision_info) | Hooks after the virtual function.
The callback signature is `nil get_collision_info(Movable self, CollisionInfo dest)` +[CallbackId](#Aliases) | [set_pre_sprint_factor(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_sprint_factor) | Hooks before the virtual function.
The callback signature is `optional sprint_factor(Movable self)` +[CallbackId](#Aliases) | [set_post_sprint_factor(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_sprint_factor) | Hooks after the virtual function.
The callback signature is `nil sprint_factor(Movable self)` +[CallbackId](#Aliases) | [set_pre_calculate_jump_velocity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_calculate_jump_velocity) | Hooks before the virtual function.
The callback signature is `optional calculate_jump_velocity(Movable self, bool dont_ignore_liquid)` +[CallbackId](#Aliases) | [set_post_calculate_jump_velocity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_calculate_jump_velocity) | Hooks after the virtual function.
The callback signature is `nil calculate_jump_velocity(Movable self, bool dont_ignore_liquid)` +[CallbackId](#Aliases) | [set_pre_get_animation_map(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_animation_map) | Hooks before the virtual function.
The callback signature is `optional> get_animation_map(Movable self)` +[CallbackId](#Aliases) | [set_post_get_animation_map(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_animation_map) | Hooks after the virtual function.
The callback signature is `nil get_animation_map(Movable self)` +[CallbackId](#Aliases) | [set_pre_apply_velocity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_apply_velocity) | Hooks before the virtual function.
The callback signature is `bool apply_velocity(Movable self, Vec2 velocities, bool ignore_weight)` +[CallbackId](#Aliases) | [set_post_apply_velocity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_apply_velocity) | Hooks after the virtual function.
The callback signature is `nil apply_velocity(Movable self, Vec2 velocities, bool ignore_weight)` +[CallbackId](#Aliases) | [set_pre_get_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_damage) | Hooks before the virtual function.
The callback signature is `optional get_damage(Movable self)`
Virtual function docs:
Returns the damage that the entity deals +[CallbackId](#Aliases) | [set_post_get_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_damage) | Hooks after the virtual function.
The callback signature is `nil get_damage(Movable self)`
Virtual function docs:
Returns the damage that the entity deals [CallbackId](#Aliases) | [set_pre_is_on_fire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_is_on_fire) | Hooks before the virtual function.
The callback signature is `optional is_on_fire(Movable self)` [CallbackId](#Aliases) | [set_post_is_on_fire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_is_on_fire) | Hooks after the virtual function.
The callback signature is `nil is_on_fire(Movable self)` -[CallbackId](#Aliases) | [set_pre_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_damage) | Hooks before the virtual function.
The callback signature is `optional damage(Movable self, Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected, damage_dealer should break etc. false if the event should be ignored by damage_dealer? -[CallbackId](#Aliases) | [set_post_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_damage) | Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected, damage_dealer should break etc. false if the event should be ignored by damage_dealer? -[CallbackId](#Aliases) | [set_pre_on_hit(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_on_hit) | Hooks before the virtual function.
The callback signature is `bool on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls on_damage with 0 damage. -[CallbackId](#Aliases) | [set_post_on_hit(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_on_hit) | Hooks after the virtual function.
The callback signature is `nil on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls on_damage with 0 damage. +[CallbackId](#Aliases) | [set_pre_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_damage) | Hooks before the virtual function.
The callback signature is `optional damage(Movable self, Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer +[CallbackId](#Aliases) | [set_post_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_damage) | Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer +[CallbackId](#Aliases) | [set_pre_on_hit(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_on_hit) | Hooks before the virtual function.
The callback signature is `bool on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. +[CallbackId](#Aliases) | [set_post_on_hit(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_on_hit) | Hooks after the virtual function.
The callback signature is `nil on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. +[CallbackId](#Aliases) | [set_pre_get_damage_sound(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_damage_sound) | Hooks before the virtual function.
The callback signature is `optional get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence +[CallbackId](#Aliases) | [set_post_get_damage_sound(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_damage_sound) | Hooks after the virtual function.
The callback signature is `nil get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence [CallbackId](#Aliases) | [set_pre_stun(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stun) | Hooks before the virtual function.
The callback signature is `bool stun(Movable self, int framecount)` [CallbackId](#Aliases) | [set_post_stun(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stun) | Hooks after the virtual function.
The callback signature is `nil stun(Movable self, int framecount)` -[CallbackId](#Aliases) | [set_pre_freeze(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_freeze) | Hooks before the virtual function.
The callback signature is `bool freeze(Movable self, int framecount)` -[CallbackId](#Aliases) | [set_post_freeze(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_freeze) | Hooks after the virtual function.
The callback signature is `nil freeze(Movable self, int framecount)` +[CallbackId](#Aliases) | [set_pre_freeze(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_freeze) | Hooks before the virtual function.
The callback signature is `bool freeze(Movable self, int framecount, bool ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time +[CallbackId](#Aliases) | [set_post_freeze(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_freeze) | Hooks after the virtual function.
The callback signature is `nil freeze(Movable self, int framecount, bool ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time [CallbackId](#Aliases) | [set_pre_light_on_fire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_light_on_fire) | Hooks before the virtual function.
The callback signature is `bool light_on_fire(Movable self, int time)`
Virtual function docs:
Does not damage entity [CallbackId](#Aliases) | [set_post_light_on_fire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_light_on_fire) | Hooks after the virtual function.
The callback signature is `nil light_on_fire(Movable self, int time)`
Virtual function docs:
Does not damage entity [CallbackId](#Aliases) | [set_pre_set_cursed(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_set_cursed) | Hooks before the virtual function.
The callback signature is `bool set_cursed(Movable self, bool b, bool effect)` [CallbackId](#Aliases) | [set_post_set_cursed(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_set_cursed) | Hooks after the virtual function.
The callback signature is `nil set_cursed(Movable self, bool b, bool effect)` [CallbackId](#Aliases) | [set_pre_web_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_web_collision) | Hooks before the virtual function.
The callback signature is `bool web_collision(Movable self)` [CallbackId](#Aliases) | [set_post_web_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_web_collision) | Hooks after the virtual function.
The callback signature is `nil web_collision(Movable self)` -[CallbackId](#Aliases) | [set_pre_check_out_of_bounds(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_check_out_of_bounds) | Hooks before the virtual function.
The callback signature is `bool check_out_of_bounds(Movable self)` -[CallbackId](#Aliases) | [set_post_check_out_of_bounds(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_check_out_of_bounds) | Hooks after the virtual function.
The callback signature is `nil check_out_of_bounds(Movable self)` +[CallbackId](#Aliases) | [set_pre_check_out_of_bounds(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_check_out_of_bounds) | Hooks before the virtual function.
The callback signature is `bool check_out_of_bounds(Movable self)`
Virtual function docs:
Disable to not get killed outside level bounds. +[CallbackId](#Aliases) | [set_post_check_out_of_bounds(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_check_out_of_bounds) | Hooks after the virtual function.
The callback signature is `nil check_out_of_bounds(Movable self)`
Virtual function docs:
Disable to not get killed outside level bounds. +[CallbackId](#Aliases) | [set_pre_set_standing_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_set_standing_on) | Hooks before the virtual function.
The callback signature is `bool set_standing_on(Movable self, int entity_uid)` +[CallbackId](#Aliases) | [set_post_set_standing_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_set_standing_on) | Hooks after the virtual function.
The callback signature is `nil set_standing_on(Movable self, int entity_uid)` [CallbackId](#Aliases) | [set_pre_standing_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_standing_on) | Hooks before the virtual function.
The callback signature is `optional standing_on(Movable self)` [CallbackId](#Aliases) | [set_post_standing_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_standing_on) | Hooks after the virtual function.
The callback signature is `nil standing_on(Movable self)` [CallbackId](#Aliases) | [set_pre_stomped_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stomped_by) | Hooks before the virtual function.
The callback signature is `bool stomped_by(Movable self, Entity)` @@ -6956,9 +6993,9 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_pick_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_pick_up) | Hooks after the virtual function.
The callback signature is `nil pick_up(Movable self, Entity entity_to_pick_up)` [CallbackId](#Aliases) | [set_pre_picked_up_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_picked_up_by) | Hooks before the virtual function.
The callback signature is `bool picked_up_by(Movable self, Entity)` [CallbackId](#Aliases) | [set_post_picked_up_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_picked_up_by) | Hooks after the virtual function.
The callback signature is `nil picked_up_by(Movable self, Entity)` -[CallbackId](#Aliases) | [set_pre_drop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_drop) | Hooks before the virtual function.
The callback signature is `bool drop(Movable self, Entity entity_to_drop)`
Virtual function docs:
Called when dropping or throwing -[CallbackId](#Aliases) | [set_post_drop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_drop) | Hooks after the virtual function.
The callback signature is `nil drop(Movable self, Entity entity_to_drop)`
Virtual function docs:
Called when dropping or throwing -[CallbackId](#Aliases) | [set_pre_collect_treasure(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_collect_treasure) | Hooks before the virtual function.
The callback signature is `bool collect_treasure(Movable self, int value, ENT_TYPE treasure)`
Virtual function docs:
Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. +[CallbackId](#Aliases) | [set_pre_drop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_drop) | Hooks before the virtual function.
The callback signature is `bool drop(Movable self)`
Virtual function docs:
Called when dropping or throwing +[CallbackId](#Aliases) | [set_post_drop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_drop) | Hooks after the virtual function.
The callback signature is `nil drop(Movable self)`
Virtual function docs:
Called when dropping or throwing +[CallbackId](#Aliases) | [set_pre_collect_treasure(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_collect_treasure) | Hooks before the virtual function.
The callback signature is `optional collect_treasure(Movable self, int value, ENT_TYPE treasure)`
Virtual function docs:
Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. [CallbackId](#Aliases) | [set_post_collect_treasure(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_collect_treasure) | Hooks after the virtual function.
The callback signature is `nil collect_treasure(Movable self, int value, ENT_TYPE treasure)`
Virtual function docs:
Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. [CallbackId](#Aliases) | [set_pre_initialize(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_initialize) | Hooks before the virtual function.
The callback signature is `bool initialize(Movable self)` [CallbackId](#Aliases) | [set_post_initialize(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_initialize) | Hooks after the virtual function.
The callback signature is `nil initialize(Movable self)` @@ -6968,8 +7005,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_picked_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_picked_up) | Hooks after the virtual function.
The callback signature is `nil picked_up(Movable self)` [CallbackId](#Aliases) | [set_pre_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_fall) | Hooks before the virtual function.
The callback signature is `bool fall(Movable self)` [CallbackId](#Aliases) | [set_post_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_fall) | Hooks after the virtual function.
The callback signature is `nil fall(Movable self)` -[CallbackId](#Aliases) | [set_pre_apply_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_apply_friction) | Hooks before the virtual function.
The callback signature is `bool apply_friction(Movable self)` -[CallbackId](#Aliases) | [set_post_apply_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_apply_friction) | Hooks after the virtual function.
The callback signature is `nil apply_friction(Movable self)` +[CallbackId](#Aliases) | [set_pre_apply_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_apply_friction) | Hooks before the virtual function.
The callback signature is `bool apply_friction(Movable self, float, bool vertical, float)` +[CallbackId](#Aliases) | [set_post_apply_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_apply_friction) | Hooks after the virtual function.
The callback signature is `nil apply_friction(Movable self, float, bool vertical, float)` [CallbackId](#Aliases) | [set_pre_crush(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_crush) | Hooks before the virtual function.
The callback signature is `bool crush(Movable self, Entity)` [CallbackId](#Aliases) | [set_post_crush(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_crush) | Hooks after the virtual function.
The callback signature is `nil crush(Movable self, Entity)` diff --git a/src/game_api/color.hpp b/src/game_api/color.hpp index adebbd022..145e6383f 100644 --- a/src/game_api/color.hpp +++ b/src/game_api/color.hpp @@ -159,7 +159,7 @@ struct Color return *this; } - /// Comparison using RGB to avoid non-precise float value + // Comparison using RGB to avoid non-precise float value bool operator==(const Color& col) const noexcept { const auto current = get_rgba(); diff --git a/src/game_api/entities_activefloors.cpp b/src/game_api/entities_activefloors.cpp index 3888ad922..47f0d5393 100644 --- a/src/game_api/entities_activefloors.cpp +++ b/src/game_api/entities_activefloors.cpp @@ -32,7 +32,7 @@ void Drill::trigger(std::optional play_sound_effect) if (overlay != nullptr) { - overlay->remove_item_ptr(this, true); + overlay->remove_item(this, true); } move_state = 6; diff --git a/src/game_api/entities_activefloors.hpp b/src/game_api/entities_activefloors.hpp index 975354d81..63d99a900 100644 --- a/src/game_api/entities_activefloors.hpp +++ b/src/game_api/entities_activefloors.hpp @@ -12,7 +12,7 @@ struct Illumination; struct ParticleEmitterInfo; struct SoundMeta; -// Seams like all activefloors have one virtual function, but it just `return` so no reason to add it +// Seams like all activefloors have one virtual function, but it just `return` so no reason to add it, maybe "purchasable" ? class Crushtrap : public Movable { diff --git a/src/game_api/entities_chars.cpp b/src/game_api/entities_chars.cpp index 17b57f344..c29609d6a 100644 --- a/src/game_api/entities_chars.cpp +++ b/src/game_api/entities_chars.cpp @@ -140,7 +140,7 @@ void Player::let_go() { if (overlay) { - overlay->remove_item_ptr(this, true); + overlay->remove_item(this, true); // coyote_timer = 0xFF; // last_state = state; // state = 1, 9, 0xA; ? diff --git a/src/game_api/entities_items.hpp b/src/game_api/entities_items.hpp index b4e24d141..8ba88dd84 100644 --- a/src/game_api/entities_items.hpp +++ b/src/game_api/entities_items.hpp @@ -16,8 +16,21 @@ struct Inventory; struct ParticleEmitterInfo; struct PlayerSlot; struct SoundMeta; +struct SpritePosition; -class Backpack : public Movable +class Powerup : public Movable +{ + public: + virtual SpritePosition& get_hud_sprite(SpritePosition&) = 0; + // not sure why the normal powerups use apply/remove effect where backpacks use the put on/put off + virtual void apply_effect(PowerupCapable* who) = 0; + virtual void remove_effect(PowerupCapable* who) = 0; + virtual void on_putting_on(PowerupCapable* who) = 0; // only for backpacks, sets offsets etc. + virtual void on_putting_off(PowerupCapable* who) = 0; + virtual bool in_use() = 0; // for jetpack returns jetpack.flame_on, for capes Cape.floating_down, for hoverpack hoverpack.is_on, teleporter and powerpack and all other powerups return false +}; + +class Backpack : public Powerup { public: /// More like on fire trigger, the explosion happens when the timer reaches > 29 @@ -26,12 +39,6 @@ class Backpack : public Movable uint16_t unknown1; uint32_t unknown2; - virtual void v93() = 0; // always returns 0x100000007 (maybe two 32bit values, 1 and 7 ?) - virtual void v94() = 0; // just return - virtual void v95() = 0; // just return - virtual void on_putting_on(Entity* who) = 0; - virtual void on_putting_off(Entity* who) = 0; - virtual bool is_active() = 0; // for jetpack returns jetpack.flame_on, for capes Cape.floating_down, for hoverpack, hoverpack.is_on, teleporter and powerpack return false virtual void trigger_explosion() = 0; // Causes the backpack to play its warning sound and triggers the explosion }; @@ -43,6 +50,8 @@ class Jetpack : public Backpack uint16_t unknown21; uint32_t fly_time; // it's per level, not even per jetpack lol, it also adds at when it explodes uint16_t fuel; // only set the fuel for an equipped jetpack (player->items)! + + virtual float jetpack_acceleration() = 0; }; class TeleporterBackpack : public Backpack @@ -77,10 +86,6 @@ class Cape : public Backpack uint8_t padding2; uint8_t padding3; uint32_t floating_count; // it's per level, not per cape - - // clear particle? called when using backpack.trigger_explosion when the cape is about to disappear - // it's a common funciton - virtual void v100(size_t unknown) = 0; }; class VladsCape : public Cape @@ -96,7 +101,11 @@ class Purchasable : public Movable class DummyPurchasableEntity : public Purchasable { - virtual Entity* switch_entities(void*) = 0; // switches the purchasable cape with normal one + Entity* replace_entity; + bool exploding; + + /// Transfers ownership etc. for who to blame, sets the exploding bool + virtual void trigger_explosion(Entity* who) = 0; }; class Mattock : public Purchasable @@ -118,6 +127,12 @@ class Gun : public Purchasable int32_t in_chamber; }; +class Scepter : public Movable +{ + public: + uint8_t cooldown; +}; + class WebGun : public Gun { }; @@ -425,7 +440,7 @@ class Torch : public Movable int16_t unknown2; virtual void light_up(bool lit) = 0; - virtual std::pair& v_94(std::pair& value) = 0; // sets the value to some constant, runs on spawn + virtual Vec2& get_flame_offset(Vec2& output) = 0; virtual ENT_TYPE get_flame_type() = 0; }; @@ -739,7 +754,8 @@ class RollingItem : public Purchasable public: float roll_speed; // only positive numbers - virtual void on_purchase(Entity* who, int32_t unknown) = 0; // give you the powerup if you buy it + /// Skip this function for item to be unpickable + virtual void pickup(Entity* who, bool) = 0; }; class PlayerBag : public Movable @@ -749,15 +765,6 @@ class PlayerBag : public Movable int8_t ropes; }; -class Powerup : public Movable -{ - public: - virtual size_t& v93(size_t&) = 0; // get powerup id/type? - virtual void apply_effect(PowerupCapable* player) = 0; // runs when getting the powerup - virtual void remove_effect(PowerupCapable* player) = 0; - // 3 more here, but they just return instantly -}; - class KapalaPowerup : public Powerup { public: @@ -852,7 +859,7 @@ class PrizeDispenser : public Movable class Bow : public Purchasable { public: - // When lain on the ground + /// When lain on the ground virtual float get_arrow_special_offset() = 0; }; diff --git a/src/game_api/entities_monsters.hpp b/src/game_api/entities_monsters.hpp index 06f73b161..9a5d35bb3 100644 --- a/src/game_api/entities_monsters.hpp +++ b/src/game_api/entities_monsters.hpp @@ -1,6 +1,7 @@ #pragma once #include "containers/custom_set.hpp" +#include "containers/custom_vector.hpp" #include "entities_chars.hpp" #include "movable.hpp" #include "particles.hpp" @@ -14,21 +15,17 @@ class Monster : public PowerupCapable int32_t chased_target_uid; uint32_t target_selection_timer; - virtual void increase_killcount() = 0; // increases state.kills_npc, is not called for normal monsters but they all have the same function - - virtual void on_aggro(uint8_t, bool) = 0; // updates state.quests in case of npc - - virtual void unknown_v97() = 0; // can't trigger it - - virtual void on_shop_entered() = 0; - + virtual void increase_killcount() = 0; // 95, increases state.kills_npc, is not called for normal monsters but they all have the same function + virtual void on_aggro(uint8_t, bool) = 0; // 96, updates state.quests in case of npc + virtual void unknown_v97() = 0; // 97, can't trigger it + virtual void on_shop_entered() = 0; // 98 // shopkeeper will walk towards you (doesn't work for Yang, even though he has the same virtual) // if disabled some monster will stop moving (like bats, jiangshi) some wont attack (crabman), shopkeeper can still kick you but won't fire his weapon - virtual void attack_logic_related() = 0; - - virtual bool update_target(Entity* ent) = 0; + virtual void attack_logic_related(uint8_t, float) = 0; // 99 + virtual bool update_target(Entity* ent, float&) = 0; // 100, float from the function above, also works as an output? }; +// RoomOwner and NPC may have common subclass for the first two virtuals, but they later dirvarge, wepon type is the same spot, but they probably just made one first then copied over the virtuals class RoomOwner : public Monster { public: @@ -49,43 +46,25 @@ class RoomOwner : public Monster uint16_t padding1; uint32_t padding2; - virtual void on_criminal_act_committed(uint8_t) = 0; // shows the appropriate message (vandal, cheater, ...) - + virtual void on_criminal_act_committed(uint8_t reason) = 0; // shows the appropriate message (vandal, cheater, ...) // for shopkeepers: checks state.shoppie_aggro_levels, for waddler checks the state.quest_flags // if you return false, but you have attacked them before, they will be patrolling but won't attack you on sight - virtual bool should_attack_on_sight() = 0; + virtual bool should_attack_on_sight() = 0; // Tusk and Yang always return false (Yang won't show anymore if attacked before, Tusk is aggroed from the start on 6-3 when you attacked her in tidepool) + virtual bool is_angry_flag_set() = 0; // checks state.level_flags 10-16 depending on the monster - virtual bool is_angry_flag_set() = 0; // checks state.level_flags 10-16 depending on the monster - - // for shopkeeper: sets shopkeeper.shotgun_attack_delay to 6 + // only for shopkeeper: sets shopkeeper.shotgun_attack_delay to 6 // triggers only at the start when aggroed - // does nothing for yang, waddler, tun virtual void set_initial_attack_delay() = 0; - virtual Entity* on_spawn_weapon() = 0; // return the weapon entity that will be used to attack the player - + virtual Entity* spawn_weapon() = 0; // return the weapon entity that will be used to attack the player virtual ENT_TYPE weapon_type() = 0; // the entity type of the weapon that will be spawned to attack the player + /// For weapons, checks if the entity should hit the trigger or not + virtual bool should_attack(std::tuple target) = 0; // parameter is some struct that contains the target - virtual bool can_attack() = 0; // parameter is some struct that contains the target - - virtual void unknown_v108() = 0; // for shopkeepers, it loops over (some of) the items for sale - + virtual void unknown_v108() = 0; // for shopkeepers, it loops over (some of) the items for sale virtual void on_death_treasure_drop() = 0; // coins and if you're lucky, gold bar from shopkeeper }; -class WalkingMonster : public Monster -{ - public: - int32_t chatting_to_uid; - /// alternates between walking and pausing every time it reaches zero - int16_t walk_pause_timer; - /// used for chatting with other monsters, attack cooldowns etc. - int16_t cooldown_timer; - // Aggro or calm, if forced to return 0 it will not aggro unless you overlap his hitbox. For caveman this is called when he wakes up (from sleep or stun) - virtual bool can_aggro() = 0; - virtual void v_102() = 0; // parameter is some struct, that it changes and returns it (looks like 3x bool and more) -}; - class NPC : public Monster { public: @@ -103,12 +82,27 @@ class NPC : public Monster virtual void on_criminal_act_committed() = 0; virtual bool should_attack_on_sight() = 0; - virtual void v_103() = 0; // take some struct as parameter, sets the first qword to some constant (also returns it?), the first thing in the struct is acutally two floats - virtual void on_interaction() = 0; // does the quests stuff etc. - virtual Entity* on_spawn_weapon() = 0; + virtual Vec2& v_103(Vec2&) = 0; // only accessed when not angered + virtual void on_interaction(bool, bool) = 0; // does the quests stuff etc. + /// Do not use this function for Tusk or Waddler, small oversight by the devs, they never call this function for them, which would try to spawn entity type 0 + virtual Entity* spawn_weapon() = 0; virtual ENT_TYPE weapon_type() = 0; - virtual bool can_attack() = 0; // parameter is some struct that contains the target - virtual void on_criminal_act_committed2() = 0; // calls the on_criminal_act_committed except for bodyguard which calls the should_attack_on_sight and turns off any speechbubble + /// For weapons, checks if the entity should hit the trigger or not + virtual bool should_attack(std::tuple target) = 0; + virtual void on_criminal_act_committed2(void*) = 0; // calls the on_criminal_act_committed except for bodyguard which calls the should_attack_on_sight and turns off any speechbubble +}; + +class WalkingMonster : public Monster +{ + public: + int32_t chatting_to_uid; + /// alternates between walking and pausing every time it reaches zero + int16_t walk_pause_timer; + /// used for chatting with other monsters, attack cooldowns etc. + int16_t cooldown_timer; + // Aggro or calm, if forced to return 0 it will not aggro unless you overlap his hitbox. For caveman this is called when he wakes up (from sleep or stun) + virtual bool can_aggro() = 0; + virtual Entity* v_102(Entity*) = 0; // returns the same entity as provided in the parameter }; enum class GHOST_BEHAVIOR : uint8_t @@ -434,6 +428,7 @@ class Leprechaun : public WalkingMonster uint16_t gold; uint8_t timer_after_humping; uint8_t unknown; + custom_vector collected_treasure; }; class Crocman : public WalkingMonster @@ -724,13 +719,14 @@ class YetiQueen : public Monster uint32_t walk_pause_timer; // alternates between walking and pausing every time it reaches zero uint8_t unknown_timer; - virtual void v_101() = 0; // can't trigger - virtual void attack_related() = 0; // parameter is some struct, if disabled it doesn't do jump attack, but still does the protect head thing - virtual void v_103() = 0; // return - virtual void jump_related() = 0; // if disabled she squads but never makes the jump - virtual void on_death() = 0; // spawns the drops + virtual void v_101() = 0; // can't trigger + virtual void attack_related(float[4]) = 0; // parameter is some struct, if disabled it doesn't do jump attack, but still does the protect head thing + virtual void v_103() = 0; // return + virtual void jump_related() = 0; // if disabled she squads but never makes the jump + virtual void on_death() = 0; // spawns the drops }; +// TODO: YetiKing should inherence from YetiQueen, should probably change the name of YetiQueen, since we don't know much about the functions and all, i leave it for someone in the future to deal with this xd class YetiKing : public Monster { public: @@ -743,11 +739,11 @@ class YetiKing : public Monster ParticleEmitterInfo* particle_dust; ParticleEmitterInfo* particle_sparkles; - virtual void v_101() = 0; // can't trigger - virtual void attack_related() = 0; // parameter is some struct, if disabled it doesn't do jump attack, but still does the protect head thing - virtual void on_attack() = 0; // freezes stuff when attacks and spawns particles - virtual void screem_related() = 0; // if disabled he opens the mount but never screams - virtual void on_death() = 0; // spawns the drops + virtual void v_101() = 0; // can't trigger + virtual void attack_related(float[4]) = 0; // parameter is some struct, if disabled it doesn't do jump attack, but still does the protect head thing + virtual void on_attack() = 0; // freezes stuff when attacks and spawns particles + virtual void screem_related() = 0; // if disabled he opens the mount but never screams + virtual void on_death() = 0; // spawns the drops }; class Lamassu : public Monster diff --git a/src/game_api/entities_mounts.hpp b/src/game_api/entities_mounts.hpp index 2a52c7a35..8afaa1720 100644 --- a/src/game_api/entities_mounts.hpp +++ b/src/game_api/entities_mounts.hpp @@ -33,18 +33,18 @@ class Mount : public PowerupCapable flags = flags | 0x20000; } - virtual Vec2& get_special_offset(Vec2& offset) = 0; // gets special offset for the raider when jumping on mount - virtual Vec2& v96(Vec2& value) = 0; // gets something for when crouching on mount - virtual bool used_double_jump() = 0; // checks can_doublejump and unknown9b - virtual uint32_t v98(bool) = 0; // returns some constant value - virtual uint32_t v99() = 0; // returns some constant value - virtual void play_jump_on_sound() = 0; // checks if it has rider - virtual void remove_rider() = 0; - virtual float v102() = 0; // get offset? mech returns 0.9, the rest 0.5 - virtual uint32_t v103() = 0; // returns some constant value - virtual uint32_t v104() = 0; // returns some constant value - virtual uint32_t v105() = 0; // returns some constant value - virtual bool can_play_mount_sound() = 0; // called every frame, if returns true mount will make a sound + virtual Vec2& get_special_offset(Vec2& offset) = 0; // 95, gets special offset for the raider when jumping on mount + virtual Vec2& v96(Vec2& value) = 0; // 96, gets something for when crouching on mount + virtual bool used_double_jump() = 0; // 97, checks can_doublejump and unknown9b + virtual uint32_t get_jump_sound(bool double_jump) = 0; // 98 + virtual uint32_t get_attack_sound() = 0; // 99 + virtual void play_jump_on_sound() = 0; // 100, checks if it has rider etc. get's sound from 103 virtual + virtual void remove_rider() = 0; // 101 + virtual float v102() = 0; // 102, get offset? mech returns 0.9, the rest 0.5 + virtual uint32_t get_mount_sound() = 0; // 103, all return the VANILLA_SOUND.MOUNTS_MOUNT sound id + virtual uint32_t get_walking_sound() = 0; // 104 + virtual uint32_t get_untamed_loop_sound() = 0; // 105 + virtual bool can_play_mount_sound() = 0; // 106, called every frame, if returns true mount will make a sound }; class Rockdog : public Mount diff --git a/src/game_api/entity.cpp b/src/game_api/entity.cpp index 11d40f7ca..379fdb16b 100644 --- a/src/game_api/entity.cpp +++ b/src/game_api/entity.cpp @@ -33,7 +33,7 @@ using namespace std::chrono_literals; void Entity::teleport(float dx, float dy, bool s, float vx, float vy, bool snap) { if (overlay) - overlay->remove_item(uid, false); + overlay->remove_item(this, false); auto topmost = topmost_mount(); // we just detached from overlay, why do we check this? if (!s) @@ -78,7 +78,7 @@ void Entity::teleport(float dx, float dy, bool s, float vx, float vy, bool snap) void Entity::teleport_abs(float dx, float dy, float vx, float vy) { if (overlay) - overlay->remove_item(uid, false); + overlay->remove_item(this, false); x = dx; y = dy; @@ -178,11 +178,11 @@ Vec2 Entity::position() const return {x_pos, y_pos}; } -void Entity::remove_item(uint32_t item_uid, bool check_autokill) +void Entity::remove_item_uid(uint32_t item_uid, bool check_autokill) { auto entity = get_entity_ptr(item_uid); if (entity) - remove_item_ptr(entity, check_autokill); + remove_item(entity, check_autokill); } void Movable::poison(int16_t frames) diff --git a/src/game_api/entity.hpp b/src/game_api/entity.hpp index 0edc5ce31..14fe71a99 100644 --- a/src/game_api/entity.hpp +++ b/src/game_api/entity.hpp @@ -193,7 +193,7 @@ class Entity { return Vec2{x, y}; } - void remove_item(uint32_t item_uid, bool check_autokill); + void remove_item_uid(uint32_t item_uid, bool check_autokill); TEXTURE get_texture() const; /// Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one @@ -261,9 +261,9 @@ class Entity inline static std::function)> hook_dtor_impl{}; inline static std::function clear_dtor_impl{}; - virtual ~Entity() = 0; // vritual 0 - virtual void create_rendering_info() = 0; // 1, potentially also returns the pointer - virtual void handle_state_machine() = 0; // 2 + virtual ~Entity() = 0; // virtual 0 + virtual void create_rendering_info() = 0; // 1 + virtual void update_state_machine() = 0; // 2 /// Kills the entity, you can set responsible to `nil` to ignore it virtual void kill(bool destroy_corpse, Entity* responsible) = 0; // 3 @@ -279,22 +279,22 @@ class Entity virtual void generate_stomp_damage_particles(Entity* victim, DAMAGE_TYPE damage, bool) = 0; // 8, particles when jumping on top of enemy virtual float get_type_field_a8() = 0; // 9 virtual bool can_be_pushed() = 0; // 10, (runs only for activefloors?) checks if entity type is pushblock, for chained push block checks ChainedPushBlock.is_chained, is only a check that allows for the pushing animation - virtual bool v11() = 0; // 11, for arrows: returns true if it's moving (for y possibly checks for some speed as well?) + virtual bool v11() = 0; // 11, is in motion? (only projectiles and some weapons) /// Returns true if entity is in water/lava - virtual bool is_in_liquid() = 0; // 12 + virtual bool is_in_liquid() = 0; // 12, drill always returns false virtual bool check_type_properties_flags_19() = 0; // 13, checks (properties_flags >> 0x12) & 1; for hermitcrab checks if he's invisible; can't get it to trigger - virtual uint8_t get_type_field_60() = 0; // 14 + virtual uint8_t get_type_field_60() = 0; // 14, the value is compared to entity state and used in some bahavior function virtual void set_invisible(bool value) = 0; // 15 - virtual void handle_turning_left(bool apply) = 0; // 16, if disabled, monsters don't turn left and keep walking in the wall (and other right-left issues) + virtual void flip(bool left) = 0; // 16 virtual void set_draw_depth(uint8_t draw_depth, uint8_t b3f) = 0; // 17 - virtual void resume_ai() = 0; // 18, works on entities with ai_func != 0; runs when companions are let go from being held. AI resumes anyway in 1.23.3, only calls `set_draw_depth` + virtual void reset_draw_depth() = 0; // 18 virtual float friction() = 0; // 19 virtual void set_as_sound_source(SoundMeta*) = 0; // 20, update sound position to entity position? - virtual void remove_item_ptr(Entity* entity, bool autokill_check) = 0; // 21, if autokill_check is true, it will check if the entity has the "kill if overlay lost" flag and kill it if it's set + virtual void remove_item(Entity* entity, bool autokill_check) = 0; // 21, if autokill_check is true, it will check if the entity has the "kill if overlay lost" flag and kill it if it's set virtual Entity* get_held_entity() = 0; // 22 virtual void v23(Entity* logical_trigger, Entity* who_triggered_it) = 0; // 23, spawns LASERTRAP_SHOT from LASERTRAP, also some trigger entities use this, seam to be called right after "on_collision2", tiggers use self as the first parameter. Called when there is entity overlapping trigger entity, even if they don't move /// Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) - virtual bool trigger_action(Entity* user) = 0; // 24 + virtual bool trigger_action(Entity* user) = 0; // 24, also used for throwables, disabling this for bomb make it always spawn an the ground, but you can still pick it up and throw it /// Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) virtual void activate(Entity* activator) = 0; // 25 @@ -302,14 +302,15 @@ class Entity virtual void on_collision2(Entity* other_entity) = 0; // 26 /// e.g. for turkey: stores health, poison/curse state, for mattock: remaining swings (returned value is transferred) - virtual uint16_t get_metadata() = 0; // 27 - virtual void apply_metadata(uint16_t metadata) = 0; // 28 - virtual void on_walked_on_by(Entity* walker) = 0; // 29, hits when monster/player walks on a floor, does something when walker.velocityy<-0.21 (falling onto) and walker.hitboxy * hitboxx > 0.09 - virtual void on_walked_off_by(Entity* walker) = 0; // 30, appears to be disabled in 1.23.3? hits when monster/player walks off a floor, it checks whether the walker has floor as overlay, and if so, removes walker from floor's items by calling virtual remove_item_ptr - virtual void on_ledge_grab(Entity* who) = 0; // 31, only ACTIVEFLOOR_FALLING_PLATFORM, does something with game menager - virtual void on_stood_on_by(Entity* entity) = 0; // 32, e.g. pots, skulls, pushblocks, ... standing on floors - virtual void toggle_backlayer_illumination() = 0; // 33, only for CHAR_*: when going to the backlayer, turns on player emitted light - virtual void v34() = 0; // 34, only ITEM_TORCH, calls Torch.light_up(false), can't get it to trigger + virtual uint16_t get_metadata() = 0; // 27 + virtual void apply_metadata(uint16_t metadata) = 0; // 28 + virtual void on_walked_on_by(Entity* walker) = 0; // 29, hits when monster/player walks on a floor, does something when walker.velocityy<-0.21 (falling onto) and walker.hitboxy * hitboxx > 0.09 + virtual void on_walked_off_by(Entity* walker) = 0; // 30, appears to be disabled in 1.23.3? hits when monster/player walks off a floor, it checks whether the walker has floor as overlay, and if so, removes walker from floor's items by calling virtual remove_item + virtual void on_ledge_grab(Entity* who) = 0; // 31, only ACTIVEFLOOR_FALLING_PLATFORM, does something with game menager + virtual void on_stood_on_by(Entity* entity, Vec2*) = 0; // 32, e.g. pots, skulls, pushblocks, ... standing on floors. The Vec2 is just a guess, it only compares Y with 0.1f + /// only for CHAR_*: when going to the backlayer, turns on/off player emitted light + virtual void toggle_backlayer_illumination() = 0; // 33 + virtual void v34() = 0; // 34, only ITEM_TORCH, calls Torch.light_up(false), can't get it to trigger /// `clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 virtual void liberate_from_shop(bool clear_parrent) = 0; // 35, can also be seen as event: when you anger the shopkeeper, this function gets called for each item; can be called on shopitems individually as well and they become 'purchased' diff --git a/src/game_api/math.hpp b/src/game_api/math.hpp index 90a80d278..03f9cd8d9 100644 --- a/src/game_api/math.hpp +++ b/src/game_api/math.hpp @@ -410,7 +410,7 @@ struct Triangle bool is_point_inside_triangle(float x, float y, std::optional epsilon); */ - /// Returns the corners + // Returns the corners operator std::tuple() const noexcept { return {A, B, C}; @@ -559,7 +559,7 @@ struct Quad Quad& offset_quad(float off_x, float off_y); */ - /// Returns the corners in order: bottom_left, bottom_right, top_right, top_left + // Returns the corners in order: bottom_left, bottom_right, top_right, top_left operator std::tuple() const noexcept { return {{bottom_left_x, bottom_left_y}, {bottom_right_x, bottom_right_y}, {top_right_x, top_right_y}, {top_left_x, top_left_y}}; diff --git a/src/game_api/member_function.hpp b/src/game_api/member_function.hpp new file mode 100644 index 000000000..fbf5c84f2 --- /dev/null +++ b/src/game_api/member_function.hpp @@ -0,0 +1,90 @@ +#include +#include + +template +struct MemberFun_t; + +namespace +{ +template +struct MemberFunBase +{ + using Pointer = R (C::*)(Args...); + using BaseLessType = R(Args...); + using BaseType = C; + using ReturnType = R; + // can't transfer the parameters by itself + using Parameters_Tuple = std::tuple; + static constexpr std::size_t ArgCount = sizeof...(Args); + template + using ArgType = std::tuple_element_t; +}; +} // namespace + +template +struct MemberFun_t : MemberFunBase +{ +}; +template +struct MemberFun_t : MemberFunBase +{ +}; +template +struct MemberFun_t : MemberFunBase +{ +}; +template +struct MemberFun_t : MemberFunBase +{ +}; +template +struct MemberFun_t : MemberFunBase +{ +}; +template +struct MemberFun_t : MemberFunBase +{ +}; + +template +struct MemberFun_t : MemberFunBase +{ +}; +template +struct MemberFun_t : MemberFunBase +{ +}; +template +struct MemberFun_t : MemberFunBase +{ +}; +template +struct MemberFun_t : MemberFunBase +{ +}; +template +struct MemberFun_t : MemberFunBase +{ +}; +template +struct MemberFun_t : MemberFunBase +{ +}; + +template +struct MemberFun +{ + private: + using FunT = decltype(fun); + static_assert(std::is_member_function_pointer_v); + public: + using Pointer = MemberFun_t::Pointer; + using BaseLessType = MemberFun_t::BaseLessType; + using BaseType = MemberFun_t::BaseType; + using ReturnType = MemberFun_t::ReturnType; + // can't transfer the parameters by itself + using Parameters_Tuple = MemberFun_t::Parameters_Tuple; + static constexpr std::size_t ArgCount = MemberFun_t::ArgCount; + template + using ArgType = std::tuple_element_t; +}; diff --git a/src/game_api/movable.hpp b/src/game_api/movable.hpp index b2d631dcb..8bd4f56e6 100644 --- a/src/game_api/movable.hpp +++ b/src/game_api/movable.hpp @@ -80,7 +80,8 @@ class Movable : public Entity uint8_t unknown_damage_counter_b; uint8_t i120a; // timer, damage related uint8_t i120b; // timer - uint8_t i120c; // timer + /// Makes you immune to the item you just thrown for short time + uint8_t throw_damage_immunity_timer; uint8_t i120d; uint8_t b124; uint8_t falling_timer; @@ -160,21 +161,23 @@ class Movable : public Entity virtual bool can_jump() = 0; // 37 virtual void get_collision_info(CollisionInfo& dest) = 0; // 38, from entityDB virtual float sprint_factor() = 0; // 39, from entityDB - virtual float calculate_jump_velocity() = 0; // 40 + virtual float calculate_jump_velocity(bool dont_ignore_liquid) = 0; // 40 virtual std::unordered_map& get_animation_map() = 0; // 41 virtual void apply_velocity(Vec2& velocities, bool ignore_weight) = 0; // 42 - /// Returns stomp damage based on shoes and fall time - virtual int8_t stomp_damage() = 0; // 43, calculates the amount of stomp damage applied (checks spike shoes, movable.state and stand_counter resulting in different damage values) - virtual int8_t stomp_damage_trampoline() = 0; // 44, simply jumps to the 43rd virtual function, aka stomp_damage... - virtual bool is_on_fire() = 0; // 45 - virtual bool v46(Entity*) = 0; // 46, on_melee_attack? called on monsters when you touch them - virtual bool v47(Entity*) = 0; // 47, actual on_thrown_by ? + /// Returns the damage that the entity deals + virtual int8_t get_damage() = 0; // 43, for player it calculates stomp damages as that's the only damage that the player entity can deal, the "normal" damage is done by the whip + virtual int8_t get_stomp_damage() = 0; // 44, calls get_damage except for mech which always returns 3, runs on stomping enemy + virtual bool is_on_fire() = 0; // 45 + /// Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) + virtual bool attack(Entity* victim) = 0; // 46 + /// Same as above, but for being thrown into something and potentially dealing damage that way + virtual bool thrown_into(Entity* victim) = 0; // 47 /// Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil. - /// Returns: true if entity was affected, damage_dealer should break etc. false if the event should be ignored by damage_dealer? + /// Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer virtual bool damage(Entity* damage_dealer, int8_t damage_amount, DAMAGE_TYPE damage_flags, Vec2* velocity, uint8_t unknown_damage_phase, uint16_t stun_amount, uint8_t iframes, bool unknown_is_final) = 0; // 48 - /// Hit by broken arrows etc that don't deal damage, calls on_damage with 0 damage. + /// Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. virtual void on_hit(Entity* damage_dealer) = 0; // 49 /// returns sound id for the damage taken, return 0 to make it silence virtual uint32_t get_damage_sound(DAMAGE_TYPE damage) = 0; // 50 @@ -189,43 +192,44 @@ class Movable : public Entity virtual void set_last_owner_uid_b127(Entity* owner) = 0; // 56, assigns player as last_owner_uid and also manipulates movable.b127 virtual uint32_t get_last_owner_uid() = 0; // 57, for players, it checks !stunned && !frozen && !cursed && !has_overlay; for others: just returns last_owner_uid /// Disable to not get killed outside level bounds. - virtual void check_out_of_bounds() = 0; // 58, kills with the 'still falling' death cause, is called for any item/fx/mount/monster/player - virtual void set_standing_on(int32_t entity_uid) = 0; // 59 - virtual Entity* standing_on() = 0; // 60, looks up movable.standing_on_uid in state.instance_id_to_pointer - virtual bool on_stomped_on_by(Entity* stomper) = 0; // 61 - virtual void on_thrown_by(Entity* thrower) = 0; // 62, implemented for special cases like hired hand (player with ai_func), horned lizard... - virtual void on_clonegunshot_hit(Entity* clone, int32_t some_entity_uid) = 0; // 63, implemented for player/hired hand: copies health to clone etc - virtual uint32_t get_type_id() = 0; // 64 - virtual bool doesnt_have_spikeshoes() = 0; // 65 - virtual bool is_player_mount_or_monster() = 0; // 66 - virtual void pick_up(Entity* entity_to_pick_up) = 0; // 67 - virtual void on_picked_up_by(Entity* entity_picking_up, bool) = 0; // 68 + virtual void check_out_of_bounds() = 0; // 58, kills with the 'still falling' death cause, is called for any item/fx/mount/monster/player + virtual void set_standing_on(int32_t entity_uid) = 0; // 59 + virtual Entity* standing_on() = 0; // 60, looks up movable.standing_on_uid in state.instance_id_to_pointer + virtual bool on_stomped_on_by(Entity* stomper) = 0; // 61 + virtual void on_thrown_by(Entity* thrower) = 0; // 62, implemented for special cases like hired hand (player with ai_func), horned lizard... + /// Entities must be of the same type! + virtual void copy_extra_info(Entity* clone, int32_t some_entity_uid) = 0; // 63, some_entity_uid - only used for CHAR_ entities, related to hired hand chain + virtual uint32_t get_type_id() = 0; // 64, dunno what for, implemented solely that ITEM_EXCALIBUR can return ITEM_BROKENEXCALIBUR instead + virtual bool doesnt_have_spikeshoes() = 0; // 65, potentially wrong name. For most entities checks if they are dead, frozen or stun (and apparently returns false if they are), for Yeti queen checks something in the animation_func, returns true for all the items etc. only for CHAR_ entities checks the spike shoes + virtual bool is_player_mount_or_monster() = 0; // 66, returns false for MONS_ALIENQUEEN, MONS_FIREFROG and MOUNT_MECH, for the rest checks EntityDB mask with value 7 + virtual void pick_up(Entity* entity_to_pick_up) = 0; // 67 + virtual bool can_be_picked_up_by(Entity* entity_picking_up, bool) = 0; // 68, the bool has something to do with the entity being attached to some entity already /// Called when dropping or throwing virtual void drop() = 0; // 69 /// Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. virtual bool collect_treasure(int32_t value, ENT_TYPE treasure) = 0; // 70 - virtual void apply_movement(uint8_t, uint8_t, uint8_t) = 0; // 71, disable this function and things can't move, some spin in place (might have more parameters, the first three probably all bool) - virtual void damage_entity(Entity* victim) = 0; // 72, can't trigger, maybe extra params are needed - virtual void v73() = 0; // 73 - virtual bool is_monster_or_player() = 0; // 74 + virtual bool apply_movement(uint8_t, uint8_t, uint8_t) = 0; // 71, disable this function and things can't move, some spin in place + virtual void damage_entity(Entity* victim) = 0; // 72, implemented for responsibility and journal update + virtual bool v73() = 0; // 73, checks some flags, held entity, is in liquid, floor entities around?, standing_on, does the current theme has the loop + virtual bool is_powerup_capable() = 0; // 74 virtual void initialize() = 0; // 75, e.g. cobra: set random spit_timer; bat: set random stand_counter; emerald: set price - virtual void check_is_falling() = 0; // 76, sets more_flags.falling by comparing velocityy to 0 - virtual void handle_stun_transition_animation() = 0; // 77, e.g. the wiggle the dog does when waking up from being stunned - virtual void process_input() = 0; // 78, unsure of params - virtual void post_collision_damage_related() = 0; // 79, used for enemies attacks as well? - virtual void on_picked_up() = 0; // 80, gets called after on_picked_up_by - virtual void hired_hand_related() = 0; // 81, checks ai_func, gets triggered just after throwing hired hand + virtual void check_is_falling() = 0; // 76, sets more_flags.falling by comparing velocityy to 0, sets i120a to FF, clears owner_uid, can call remove_rider on mounts, for player updates the extra y_pos, for bosses clears lock input timer + virtual void v77() = 0; // 77 + virtual void process_input() = 0; // 78, more like: handle_movment + virtual void post_collision_damage_related() = 0; // 79, used for enemies attacks as well? 3 versions for: eggplant minister, players and the rest + virtual void on_picked_up() = 0; // 80, plays pickup sound depending on the entity mask/type etc. set stun for pets and mounts etc. + virtual void on_release() = 0; // 81, only for hired hands and lava pots virtual void generate_fall_poof_particles() = 0; // 82, entity.velocityy must be < -0.12 to generate a poof, might do other stuff regarding falling/landing /// Applies gravity to entity. Disable to float like on hoverpack. virtual void handle_fall_logic(float) = 0; // 83, adjusts entity.velocityy when falling virtual void apply_friction(float, bool vertical, float) = 0; // 84, applies entity.type.friction to entity.velocityx, the two floats for characters just multiply the friction, could also be returning the value - virtual bool boss_related(bool) = 0; // 85, when disabled, quillback keeps stomping through the level, including border tiles - virtual void v86(void*, Entity*) = 0; // 86, triggers when tusk is angered, calls get_last_owner_uid - virtual void gravity_related(Entity*, float, Entity*) = 0; // 87 - virtual void v88(Entity*, float) = 0; // 88, calls on_fall_onto, then virtual 14 on the entity in parameter, edits special offset - virtual uint8_t stack_plus_28_is_0() = 0; // 89, unknown; triggers on item_rubble + virtual bool can_break_block(bool horizontal, Entity* block) = 0; // 85, check on collision if the entity should break the block, used for stuff like drill, hundun etc. surprisingly no mattoc + virtual void break_block(bool camera_shake, Entity* block) = 0; // 86 + virtual void v87(Entity* entity, float, Entity* floor, float, bool) = 0; // 87, on_contact_with_ground ? calls on_stood_on_by, on_fall_onto + virtual void v88(Entity* entity, float vecloty) = 0; // 88, on_ragdoll? - for player, triggers only when you throw him into wall/ground/celling + virtual bool v89(void*, void*, bool, bool default_return_flipped) = 0; // 89, triggers on item_rubble?, first parameter only tested if it's 0 for punishball, ignored in the rest, second parameter never used (leftover?) virtual void on_crushed_by(Entity*) = 0; // 90, e.g. crushed by elevator, punishball, pushblock, crushtrap (not quillback or boulder) - virtual SoundMeta* on_fall_onto(uint32_t play_sound_id, Entity* fell_on_entity) = 0; // 91 - virtual void on_instakill_death() = 0; // 92, seems to only trigger for enemies that die in one hit + virtual SoundMeta* on_fall_onto(uint32_t play_sound_id, Entity* fell_on_entity) = 0; // 91, plays the sfx at the entity and sets sound parameters + virtual void on_instakill_death() = 0; // 92, seems to only trigger for enemies that die in one hit, creates some big struct on stack, feeds it to some unknown function }; diff --git a/src/game_api/rpc.cpp b/src/game_api/rpc.cpp index 1e49d52d5..7c6b33eeb 100644 --- a/src/game_api/rpc.cpp +++ b/src/game_api/rpc.cpp @@ -69,7 +69,7 @@ void attach_entity(Entity* overlay, Entity* attachee) { if (attachee->overlay) { - attachee->overlay->remove_item_ptr(attachee, false); + attachee->overlay->remove_item(attachee, false); } auto [x, y] = overlay->position(); @@ -343,7 +343,7 @@ void entity_remove_item(uint32_t uid, uint32_t item_uid, std::optional che Entity* entity = get_entity_ptr(uid); if (entity == nullptr) return; - entity->remove_item(item_uid, check_autokill.value_or(true)); + entity->remove_item_uid(item_uid, check_autokill.value_or(true)); } void lock_door_at(float x, float y) diff --git a/src/game_api/script/lua_vm.cpp b/src/game_api/script/lua_vm.cpp index ecf28ecc3..59819200a 100644 --- a/src/game_api/script/lua_vm.cpp +++ b/src/game_api/script/lua_vm.cpp @@ -163,9 +163,7 @@ struct Players it_t last; lua_iterator_state(Players& mt) - : begin(mt.begin()), it(mt.begin()), last(mt.end()) - { - } + : begin(mt.begin()), it(mt.begin()), last(mt.end()){}; }; static std::tuple my_next(sol::user user_it_state, sol::this_state l) { diff --git a/src/game_api/script/sol_helper.hpp b/src/game_api/script/sol_helper.hpp index 439de3c44..b77cae34c 100644 --- a/src/game_api/script/sol_helper.hpp +++ b/src/game_api/script/sol_helper.hpp @@ -7,6 +7,8 @@ #include #include +#include "member_function.hpp" + template struct ZeroIndexArray { @@ -95,19 +97,6 @@ struct usertype_container> }; } // namespace sol -namespace detail -{ -template -struct extract; -template -struct extract -{ - using BaseType = C; - using ReturnType = R; - using Params = std::tuple; -}; -} // namespace detail - namespace { template @@ -127,9 +116,10 @@ struct proFunc, T, fun> template auto self_return() { - static_assert(std::is_member_function_pointer_v); - using T = typename detail::extract::BaseType; - using _tuple = typename detail::extract::Params; + using FunT = decltype(fun); + static_assert(std::is_member_function_pointer_v); + using T = typename MemberFun_t::BaseType; + using _tuple = typename MemberFun_t::Parameters_Tuple; return proFunc<_tuple, T, fun>::func; } diff --git a/src/game_api/script/usertypes/entities_monsters_lua.cpp b/src/game_api/script/usertypes/entities_monsters_lua.cpp index 1304b8f52..ecd3a4440 100644 --- a/src/game_api/script/usertypes/entities_monsters_lua.cpp +++ b/src/game_api/script/usertypes/entities_monsters_lua.cpp @@ -523,6 +523,8 @@ void register_usertypes(sol::state& lua) &Leprechaun::gold, "timer_after_humping", &Leprechaun::timer_after_humping, + "collected_treasure", + &Leprechaun::collected_treasure, sol::base_classes, sol::bases()); diff --git a/src/game_api/script/usertypes/entity_lua.cpp b/src/game_api/script/usertypes/entity_lua.cpp index 43645a6d6..2e00a173c 100644 --- a/src/game_api/script/usertypes/entity_lua.cpp +++ b/src/game_api/script/usertypes/entity_lua.cpp @@ -268,7 +268,9 @@ void register_usertypes(sol::state& lua) entity_type["is_cursed"] = &Entity::is_cursed; entity_type["kill_recursive"] = kill_recursive; entity_type["destroy_recursive"] = destroy_recursive; - entity_type["update"] = &Entity::handle_state_machine; + entity_type["update"] = &Entity::update_state_machine; + entity_type["flip"] = &Entity::flip; + entity_type["can_be_pushed"] = &Entity::can_be_pushed; /* Entity // user_data // You can put any arbitrary lua object here for custom entities or player stats, which is then saved across level transitions for players and carried items, mounts etc... This field is local to the script and multiple scripts can write different things in the same entity. The data is saved right before ON.PRE_LOAD_SCREEN from a level and loaded right before ON.POST_LOAD_SCREEN to a level or transition. It is not available yet in post_entity_spawn, but that is a good place to initialize it for new custom entities. See example for more. @@ -333,12 +335,13 @@ void register_usertypes(sol::state& lua) movable_type["set_cursed"] = &Movable::set_cursed_fix; movable_type["drop"] = &Movable::drop; movable_type["pick_up"] = &Movable::pick_up; - movable_type["can_jump"] = &Movable::can_jump; movable_type["standing_on"] = &Movable::standing_on; /// NoDoc movable_type["add_money"] = add_money; movable_type["collect_treasure"] = &Movable::collect_treasure; + movable_type["can_jump"] = &Movable::can_jump; movable_type["is_on_fire"] = &Movable::is_on_fire; + movable_type["is_powerup_capable"] = &Movable::is_powerup_capable; movable_type["damage"] = damage; movable_type["get_all_behaviors"] = &Movable::get_all_behaviors; movable_type["set_behavior"] = &Movable::set_behavior; diff --git a/src/game_api/script/usertypes/vtables_lua.cpp b/src/game_api/script/usertypes/vtables_lua.cpp index b6753168a..f83daa5ce 100644 --- a/src/game_api/script/usertypes/vtables_lua.cpp +++ b/src/game_api/script/usertypes/vtables_lua.cpp @@ -1,13 +1,19 @@ #include "vtables_lua.hpp" #include "entity.hpp" // for Entity +#include "entity_structs.hpp" // for CollisionInfo #include "hookable_vtable.hpp" // for HookableVTable +#include "member_function.hpp" // for MemberFun #include "movable.hpp" // for Movable #include "render_api.hpp" // for RenderInfo #include "script/usertypes/theme_vtable_lua.hpp" // for NThemeVTables #include "script/usertypes/vanilla_render_lua.hpp" // for VanillaRenderContext +#include "sound_manager.hpp" // for SoundMeta #include "state.hpp" // for State +template +using MemFun = MemberFun::BaseLessType; + namespace NVTables { void register_usertypes(sol::state& lua) @@ -18,42 +24,60 @@ void register_usertypes(sol::state& lua) using EntityVTable = HookableVTable< Entity, CallbackType::Entity, - VTableEntry<"dtor", 0x0, void()>, - VTableEntry<"create_rendering_info", 0x1, void()>, - VTableEntry<"update_state_machine", 0x2, void()>, - VTableEntry<"kill", 0x3, void(bool, Entity*)>, - VTableEntry<"on_collision1", 0x4, void(Entity*)>, - VTableEntry<"destroy", 0x5, void()>, - VTableEntry<"can_be_pushed", 0xa, bool()>, - VTableEntry<"is_in_liquid", 0xc, bool()>, - VTableEntry<"set_invisible", 0xf, void(bool)>, - VTableEntry<"friction", 0x13, float()>, - VTableEntry<"get_held_entity", 0x16, Entity*()>, - VTableEntry<"trigger_action", 0x18, void(Entity*)>, - VTableEntry<"activate", 0x19, void(Entity*)>, - VTableEntry<"on_collision2", 0x1a, void(Entity*)>, - VTableEntry<"walked_on", 0x1d, void(Entity*)>, - VTableEntry<"walked_off", 0x1e, void(Entity*)>, - VTableEntry<"ledge_grab", 0x1f, void(Entity*)>, - VTableEntry<"stood_on", 0x20, void(Entity*)>, - VTableEntry<"init", 0x24, void()>>; + VTableEntry<"dtor", 0, void()>, + VTableEntry<"create_rendering_info", 1, MemFun<&Entity::create_rendering_info>>, + VTableEntry<"update_state_machine", 2, MemFun<&Entity::update_state_machine>>, + VTableEntry<"kill", 3, MemFun<&Entity::kill>>, + VTableEntry<"on_collision1", 4, MemFun<&Entity::on_collision1>>, + VTableEntry<"destroy", 5, MemFun<&Entity::destroy>>, + VTableEntry<"generate_stomp_damage_particles", 8, MemFun<&Entity::generate_stomp_damage_particles>>, + VTableEntry<"can_be_pushed", 10, MemFun<&Entity::can_be_pushed>>, + VTableEntry<"is_in_liquid", 12, MemFun<&Entity::is_in_liquid>>, + VTableEntry<"set_invisible", 15, MemFun<&Entity::set_invisible>>, + VTableEntry<"flip", 16, MemFun<&Entity::flip>>, + VTableEntry<"set_draw_depth", 17, MemFun<&Entity::set_draw_depth>>, + VTableEntry<"reset_draw_depth", 18, MemFun<&Entity::reset_draw_depth>>, + VTableEntry<"friction", 19, MemFun<&Entity::friction>>, + VTableEntry<"set_as_sound_source", 20, MemFun<&Entity::set_as_sound_source>>, + VTableEntry<"remove_item", 21, MemFun<&Entity::remove_item>>, + VTableEntry<"get_held_entity", 22, MemFun<&Entity::get_held_entity>>, + VTableEntry<"trigger_action", 24, MemFun<&Entity::trigger_action>>, + VTableEntry<"activate", 25, MemFun<&Entity::activate>>, + VTableEntry<"on_collision2", 26, MemFun<&Entity::on_collision2>>, + VTableEntry<"get_metadata", 27, MemFun<&Entity::get_metadata>>, + VTableEntry<"apply_metadata", 28, MemFun<&Entity::apply_metadata>>, + VTableEntry<"walked_on", 29, MemFun<&Entity::on_walked_on_by>>, + VTableEntry<"walked_off", 30, MemFun<&Entity::on_walked_off_by>>, + VTableEntry<"ledge_grab", 31, MemFun<&Entity::on_ledge_grab>>, + VTableEntry<"stood_on", 32, MemFun<&Entity::on_stood_on_by>>, + VTableEntry<"liberate_from_shop", 35, MemFun<&Entity::liberate_from_shop>>, + VTableEntry<"init", 36, MemFun<&Entity::apply_db>>>; static EntityVTable entity_vtable(lua, lua["Entity"], "ENTITY_OVERRIDE"); using MovableVTable = HookableVTable< Entity, CallbackType::Entity, EntityVTable, - VTableEntry<"can_jump", 37, bool()>, - VTableEntry<"stomp_damage", 43, int8_t()>, + VTableEntry<"can_jump", 37, MemFun<&Movable::can_jump>>, + VTableEntry<"get_collision_info", 38, MemFun<&Movable::get_collision_info>>, + VTableEntry<"sprint_factor", 39, MemFun<&Movable::sprint_factor>>, + VTableEntry<"calculate_jump_velocity", 40, MemFun<&Movable::calculate_jump_velocity>>, + // VTableEntry<"get_animation_map", 41, MemFun<&Movable::get_animation_map>>, + VTableEntry<"apply_velocity", 42, MemFun<&Movable::apply_velocity>>, + /// NoDoc + VTableEntry<"stomp_damage", 43, MemFun<&Movable::get_damage>>, + VTableEntry<"get_damage", 43, MemFun<&Movable::get_damage>>, VTableEntry<"is_on_fire", 45, bool()>, VTableEntry<"damage", 48, bool(Entity*, int8_t, uint16_t, Vec2*, uint8_t, uint16_t, uint8_t, bool)>, VTableEntry<"on_hit", 49, void(Entity*)>, + VTableEntry<"get_damage_sound", 50, uint32_t(DAMAGE_TYPE)>, VTableEntry<"stun", 51, void(uint16_t)>, VTableEntry<"freeze", 52, void(uint8_t)>, VTableEntry<"light_on_fire", 53, void(uint8_t)>, VTableEntry<"set_cursed", 54, void(bool)>, VTableEntry<"web_collision", 55, void()>, VTableEntry<"check_out_of_bounds", 58, void()>, + VTableEntry<"set_standing_on", 59, void(int32_t)>, VTableEntry<"standing_on", 60, Entity*()>, VTableEntry<"stomped_by", 61, void(Entity*)>, VTableEntry<"thrown_by", 62, void(Entity*)>, diff --git a/src/game_api/vtable_hook.hpp b/src/game_api/vtable_hook.hpp index 3a77565b0..67a8e5e03 100644 --- a/src/game_api/vtable_hook.hpp +++ b/src/game_api/vtable_hook.hpp @@ -55,7 +55,7 @@ struct VTableDetour s_Functions[self](self, args..., s_Originals[vtable]); return; } - s_Originals[vtable](self, std::move(args)...); + s_Originals[vtable](self, args...); } else { diff --git a/src/injected/ui.cpp b/src/injected/ui.cpp index f6deaa78f..e6d08d23b 100644 --- a/src/injected/ui.cpp +++ b/src/injected/ui.cpp @@ -1875,7 +1875,7 @@ void toggle_noclip() if (options["noclip"]) { if (player->overlay) - player->overlay->remove_item(player->uid, false); + player->overlay->remove_item_uid(player->uid, false); player->type->max_speed = 0.3f; } else @@ -1915,7 +1915,7 @@ void force_cheats() player->teleport_abs(x + player->movex * 0.3f, y + player->movey * 0.07f, 0, 0); } else - player->overlay->remove_item(player->uid, false); + player->overlay->remove_item_uid(player->uid, false); } player->standing_on_uid = -1; player->flags |= 1U << 9; @@ -7525,7 +7525,7 @@ void render_entity_props(int uid, bool detached = false) } else { - mount->remove_item_ptr(entity, false); + mount->remove_item(entity, false); } } entity->overlay = nullptr; @@ -7581,7 +7581,7 @@ void render_entity_props(int uid, bool detached = false) } else { - overlay->remove_item_ptr(entity, true); + overlay->remove_item(entity, true); } } render_uid(overlay->uid, "StateAttached"); @@ -7743,7 +7743,7 @@ void render_entity_props(int uid, bool detached = false) removed_uid = ent->uid; } if (removed_uid) - entity_pow->remove_item(removed_uid, true); + entity_pow->remove_item_uid(removed_uid, true); ImGui::SeparatorText("Powerups"); int removed_powerup = 0; for (const auto& [powerup_id, powerup_entity] : entity_pow->powerups) @@ -7824,7 +7824,7 @@ void render_entity_props(int uid, bool detached = false) removed_uid = ent->uid; } if (removed_uid) - entity->remove_item(removed_uid, true); + entity->remove_item_uid(removed_uid, true); } endmenu(); } From 2fedd8b838e250a8ce7ffcf7be2da02df0a1d795 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Wed, 11 Sep 2024 22:29:22 +0200 Subject: [PATCH 03/21] fix build --- src/game_api/entities_items.hpp | 2 ++ src/game_api/entities_monsters.hpp | 8 ++++---- src/game_api/member_function.hpp | 1 + src/injected/ui.cpp | 8 ++++---- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/game_api/entities_items.hpp b/src/game_api/entities_items.hpp index 8ba88dd84..31ae1d9c7 100644 --- a/src/game_api/entities_items.hpp +++ b/src/game_api/entities_items.hpp @@ -96,11 +96,13 @@ class VladsCape : public Cape class Purchasable : public Movable { + public: virtual void buy(Entity* who) = 0; }; class DummyPurchasableEntity : public Purchasable { + public: Entity* replace_entity; bool exploding; diff --git a/src/game_api/entities_monsters.hpp b/src/game_api/entities_monsters.hpp index 9a5d35bb3..4777b62d1 100644 --- a/src/game_api/entities_monsters.hpp +++ b/src/game_api/entities_monsters.hpp @@ -15,14 +15,14 @@ class Monster : public PowerupCapable int32_t chased_target_uid; uint32_t target_selection_timer; - virtual void increase_killcount() = 0; // 95, increases state.kills_npc, is not called for normal monsters but they all have the same function + virtual void increase_killcount() = 0; // 95, increases state.kills_npc, is not called for normal monsters but they all have the same function virtual void on_aggro(uint8_t, bool) = 0; // 96, updates state.quests in case of npc - virtual void unknown_v97() = 0; // 97, can't trigger it - virtual void on_shop_entered() = 0; // 98 + virtual void unknown_v97() = 0; // 97, can't trigger it + virtual void on_shop_entered() = 0; // 98 // shopkeeper will walk towards you (doesn't work for Yang, even though he has the same virtual) // if disabled some monster will stop moving (like bats, jiangshi) some wont attack (crabman), shopkeeper can still kick you but won't fire his weapon virtual void attack_logic_related(uint8_t, float) = 0; // 99 - virtual bool update_target(Entity* ent, float&) = 0; // 100, float from the function above, also works as an output? + virtual bool update_target(Entity* ent, float&) = 0; // 100, float from the function above, also works as an output? }; // RoomOwner and NPC may have common subclass for the first two virtuals, but they later dirvarge, wepon type is the same spot, but they probably just made one first then copied over the virtuals diff --git a/src/game_api/member_function.hpp b/src/game_api/member_function.hpp index fbf5c84f2..398dbd017 100644 --- a/src/game_api/member_function.hpp +++ b/src/game_api/member_function.hpp @@ -77,6 +77,7 @@ struct MemberFun private: using FunT = decltype(fun); static_assert(std::is_member_function_pointer_v); + public: using Pointer = MemberFun_t::Pointer; using BaseLessType = MemberFun_t::BaseLessType; diff --git a/src/injected/ui.cpp b/src/injected/ui.cpp index e6d08d23b..79c1327ac 100644 --- a/src/injected/ui.cpp +++ b/src/injected/ui.cpp @@ -1875,7 +1875,7 @@ void toggle_noclip() if (options["noclip"]) { if (player->overlay) - player->overlay->remove_item_uid(player->uid, false); + player->overlay->remove_item(player, false); player->type->max_speed = 0.3f; } else @@ -1915,7 +1915,7 @@ void force_cheats() player->teleport_abs(x + player->movex * 0.3f, y + player->movey * 0.07f, 0, 0); } else - player->overlay->remove_item_uid(player->uid, false); + player->overlay->remove_item(player, false); } player->standing_on_uid = -1; player->flags |= 1U << 9; @@ -7735,7 +7735,7 @@ void render_entity_props(int uid, bool detached = false) if (entity->type->search_flags & 0x7) { auto entity_pow = entity->as(); - int removed_uid = 0; + int removed_uid = -1; for (auto ent : entity->items.entities()) { if ((fx || (ent->type->search_flags & 0x40) == 0) && !entity_pow->has_powerup(ent->type->id)) @@ -7816,7 +7816,7 @@ void render_entity_props(int uid, bool detached = false) } else { - int removed_uid = 0; + int removed_uid = -1; for (auto ent : entity->items.entities()) { if ((fx || (ent->type->search_flags & 0x40) == 0)) From a203288678debf3952964bf2bf54a38abe8386dd Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:48:06 +0200 Subject: [PATCH 04/21] fix build 2 --- docs/parse_source.py | 5 ++--- src/game_api/entities_monsters.hpp | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/parse_source.py b/docs/parse_source.py index f7605b1d9..68fd4375e 100644 --- a/docs/parse_source.py +++ b/docs/parse_source.py @@ -638,6 +638,7 @@ def run_parse(): and item["member_funs"][func_name] and len(item["member_funs"][func_name]) > 0 ): + # choosing the last one since that's the actual virtual signature most of the time func = item["member_funs"][func_name][-1] vtable_entries[name] = { "name": name, @@ -648,9 +649,7 @@ def run_parse(): "binds": binds, } else: - signature = re.search( - r"([_a-zA-Z][\w]*.*)\((.*)\)", signature - ) + signature = re.search(r"([_a-zA-Z][\w]*.*)\((.*)\)", signature) ret = signature.group(1) args = [t for t in signature.group(2).split(",")] vtable_entries[name] = { diff --git a/src/game_api/entities_monsters.hpp b/src/game_api/entities_monsters.hpp index 4777b62d1..be6c7f2a1 100644 --- a/src/game_api/entities_monsters.hpp +++ b/src/game_api/entities_monsters.hpp @@ -581,7 +581,7 @@ class Anubis : public Monster bool awake; virtual void set_next_attack_timer() = 0; // sets next_attack_timer based on the psychic_orbs_counter - virtual void attack() = 0; + virtual void normal_attack() = 0; virtual void play_attack_sound() = 0; // also calls virtual 20 }; From 38f0d5b91e6ad09d9c29d2dafdf8714b2f6fd2c1 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 12 Sep 2024 13:11:45 +0200 Subject: [PATCH 05/21] some post merge changes, update docs --- docs/game_data/spel2.lua | 124 ++++++++++++++--------------- docs/src/includes/_types.md | 82 +++++++++---------- src/game_api/entities_items.hpp | 2 +- src/game_api/entities_monsters.hpp | 6 +- src/game_api/entity.hpp | 4 +- src/game_api/movable.hpp | 2 +- 6 files changed, 110 insertions(+), 110 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index c9a979bbb..f07860d8e 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -78,11 +78,11 @@ function lua_print() end ---@param message string ---@return nil function print(message) end ----Print a log message to ingame console with a comment identifying the script that sent it. +---Print a log message to in-game console with a comment identifying the script that sent it. ---@param message string ---@return nil function console_print(message) end ----Prinspect to ingame console. +---Prinspect to in-game console. ---@vararg any ---@return nil function console_prinspect(...) end @@ -418,7 +418,7 @@ function spawn_unrolled_player_rope(x, y, layer, texture, max_length) end ---@param layer LAYER? ---@return integer function spawn_player(player_slot, x, y, layer) end ----Spawn the PlayerGhost entity, it will not move and not be connected to any player, you can then use [steal_input](https://spelunky-fyi.github.io/overlunky/#steal_input) and send_input to controll it +---Spawn the PlayerGhost entity, it will not move and not be connected to any player, you can then use [steal_input](https://spelunky-fyi.github.io/overlunky/#steal_input) and send_input to control it ---or change it's `player_inputs` to the `input` of real player so he can control it directly ---@param char_type ENT_TYPE ---@param x number @@ -428,7 +428,7 @@ function spawn_player(player_slot, x, y, layer) end function spawn_playerghost(char_type, x, y, layer) end ---Add a callback for a spawn of specific entity types or mask. Set `mask` to `MASK.ANY` to ignore that. ---This is run before the entity is spawned, spawn your own entity and return its uid to replace the intended spawn. ----In many cases replacing the intended entity won't have the indended effect or will even break the game, so use only if you really know what you're doing. +---In many cases replacing the intended entity won't have the intended effect or will even break the game, so use only if you really know what you're doing. ---The callback signature is optional pre_entity_spawn(ENT_TYPE entity_type, float x, float y, int layer, Entity overlay_entity, SPAWN_TYPE spawn_flags) ---@param cb fun(entity_type: ENT_TYPE, x: number, y: number, layer: integer, overlay_entity: Entity, spawn_flags: SPAWN_TYPE): integer? ---@param flags SPAWN_TYPE @@ -544,7 +544,7 @@ function get_type(id) end ---@param layer LAYER ---@return integer function get_grid_entity_at(x, y, layer) end ----Get uids of static entities overlaping this grid position (decorations, backgrounds etc.) +---Get uids of static entities overlapping this grid position (decorations, backgrounds etc.) ---@param x number ---@param y number ---@param layer LAYER @@ -998,7 +998,7 @@ function raise() end ---@param hash integer ---@return STRINGID function hash_to_stringid(hash) end ----Get string behind STRINGID, don't use stringid diretcly for vanilla string, use [hash_to_stringid](https://spelunky-fyi.github.io/overlunky/#hash_to_stringid) first +---Get string behind STRINGID, don't use stringid directly for vanilla string, use [hash_to_stringid](https://spelunky-fyi.github.io/overlunky/#hash_to_stringid) first ---Will return the string of currently choosen language ---@param string_id STRINGID ---@return string @@ -1009,7 +1009,7 @@ function get_string(string_id) end ---@param str string ---@return nil function change_string(id, str) end ----Add custom string, currently can only be used for names of shop items (Entitydb->description) +---Add custom string, currently can only be used for names of shop items (EntityDB->description) ---Returns STRINGID of the new string ---@param str string ---@return STRINGID @@ -1286,12 +1286,12 @@ function set_frametime_unfocused(frametime) end ---@return double function get_frametime_unfocused() end ---Adds new custom type (group of ENT_TYPE) that can be later used in functions like get_entities_by or set_(pre/post)_entity_spawn ----Use empty array or no parameter to get new uniqe ENT_TYPE that can be used for custom EntityDB +---Use empty array or no parameter to get new unique ENT_TYPE that can be used for custom EntityDB ---@param types ENT_TYPE[] ---@return ENT_TYPE function add_custom_type(types) end ---Adds new custom type (group of ENT_TYPE) that can be later used in functions like get_entities_by or set_(pre/post)_entity_spawn ----Use empty array or no parameter to get new uniqe ENT_TYPE that can be used for custom EntityDB +---Use empty array or no parameter to get new unique ENT_TYPE that can be used for custom EntityDB ---@return ENT_TYPE function add_custom_type() end ---Get uids of entities by draw_depth. Can also use table of draw_depths. @@ -1389,7 +1389,7 @@ function play_adventure() end ---@return nil function play_seeded(seed) end ---Change layer at which the liquid spawns in, THIS FUNCTION NEEDS TO BE CALLED BEFORE THE LEVEL IS BUILD, otherwise collisions and other stuff will be wrong for the newly spawned liquid ----This sadly also makes lavamanders extinct, since the logic for their spawn is harcoded to front layer with bunch of other unrelated stuff (you can still spawn them with script or place them directly in level files) +---This sadly also makes lavamanders extinct, since the logic for their spawn is hardcoded to front layer with bunch of other unrelated stuff (you can still spawn them with script or place them directly in level files) ---Everything should be working more or less correctly (report on community discord if you find something unusual) ---@param l LAYER ---@return nil @@ -1501,7 +1501,7 @@ function extinguish_particles(particle_emitter) end ---@param layer LAYER ---@return boolean function default_spawn_is_valid(x, y, layer) end ----Check if position satifies the given POS_TYPE flags, to be used in a custom is_valid function procedural for spawns. +---Check if position satisfies the given POS_TYPE flags, to be used in a custom is_valid function procedural for spawns. ---@param x number ---@param y number ---@param layer LAYER @@ -1553,7 +1553,7 @@ function define_procedural_spawn(procedural_spawn, do_spawn, is_valid) end ---Use for example when you can spawn only on the ceiling, under water or inside a shop. ---Set `is_valid` to `nil` in order to use the default rule (aka. on top of floor and not obstructed). ---To change the number of spawns use `PostRoomGenerationContext:set_num_extra_spawns` during `ON.POST_ROOM_GENERATION` ----No name is attached to the extra spawn since it is not modified from level files, instead every call to this function will return a new uniqe id. +---No name is attached to the extra spawn since it is not modified from level files, instead every call to this function will return a new unique id. ---@param do_spawn fun(x: number, y: number, layer: LAYER): nil ---@param is_valid fun(x: number, y: number, layer: LAYER): boolean ---@param num_spawns_frontlayer integer @@ -1630,28 +1630,28 @@ function get_level_config(config) end function set_level_config(config, value) end ---Grow vines from `GROWABLE_VINE` and `VINE_TREE_TOP` entities in a level, `area` default is whole level, `destroy_broken` default is false ---@param l LAYER ----@param max_lengh integer +---@param max_length integer ---@param area AABB ---@param destroy_broken boolean ---@return nil -function grow_vines(l, max_lengh, area, destroy_broken) end +function grow_vines(l, max_length, area, destroy_broken) end ---Grow vines from `GROWABLE_VINE` and `VINE_TREE_TOP` entities in a level, `area` default is whole level, `destroy_broken` default is false ---@param l LAYER ----@param max_lengh integer +---@param max_length integer ---@return nil -function grow_vines(l, max_lengh) end +function grow_vines(l, max_length) end ---Grow pole from `GROWABLE_CLIMBING_POLE` entities in a level, `area` default is whole level, `destroy_broken` default is false ---@param l LAYER ----@param max_lengh integer +---@param max_length integer ---@param area AABB ---@param destroy_broken boolean ---@return nil -function grow_poles(l, max_lengh, area, destroy_broken) end +function grow_poles(l, max_length, area, destroy_broken) end ---Grow pole from `GROWABLE_CLIMBING_POLE` entities in a level, `area` default is whole level, `destroy_broken` default is false ---@param l LAYER ----@param max_lengh integer +---@param max_length integer ---@return nil -function grow_poles(l, max_lengh) end +function grow_poles(l, max_length) end ---Grow chains from `ENT_TYPE_FLOOR_CHAIN_CEILING` and chain with blocks on it from `ENT_TYPE_FLOOR_CHAINANDBLOCKS_CEILING`, it starts looking for the ceilings from the top left corner of a level. ---To limit it use the parameters, so x = 10 will only grow chains from ceilings with x < 10, with y = 10 it's ceilings that have y > (level bound top - 10) ---@return boolean @@ -1823,7 +1823,7 @@ function screen_aabb(box) end ---@param D Vec2 ---@return Vec2 function intersection(A, B, C, D) end ----Mesures angle between two lines with one common point +---Measures angle between two lines with one common point ---@param A Vec2 ---@param common Vec2 ---@param B Vec2 @@ -1910,7 +1910,7 @@ function get_bucket() end function rgba(r, g, b, a) end ---Convert a string to a color, you can use the HTML color names, or even HTML color codes, just prefix them with '#' symbol ---You can also convert hex string into a color, prefix it with '0x', but use it only if you need to since lua allows for hex values directly too. ----Default apha value will be 0xFF, unless it's specified +---Default alpha value will be 0xFF, unless it's specified ---Format: [name], #RRGGBB, #RRGGBBAA, 0xBBGGRR, 0xAABBGGRR ---@param color_name string ---@param alpha integer? @@ -2528,7 +2528,7 @@ function PRNG:random(min, max) end ---@field destroy fun(self): nil @Completely removes the entity from existence ---@field activate fun(self, activator: Entity): nil @Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) ---@field perform_teleport fun(self, delta_x: integer, delta_y: integer): nil @Performs a teleport as if the entity had a teleporter and used it. The delta coordinates are where you want the entity to teleport to relative to its current position, in tiles (so integers, not floats). Positive numbers = to the right and up, negative left and down. - ---@field trigger_action fun(self, user: Entity): boolean @Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) + ---@field trigger_action fun(self, user: Entity): boolean @Triggers weapons and other held items like teleporter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) ---@field get_metadata fun(self): integer @e.g. for turkey: stores health, poison/curse state, for mattock: remaining swings (returned value is transferred) ---@field apply_metadata fun(self, metadata: integer): nil ---@field set_invisible fun(self, value: boolean): nil @@ -2575,8 +2575,8 @@ function PRNG:random(min, max) end ---@field set_post_remove_item fun(self, fun: fun(self: Entity, entity: Entity, autokill_check: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil remove_item(Entity self, Entity entity, boolean autokill_check)` ---@field set_pre_get_held_entity fun(self, fun: fun(self: Entity): Entity?): CallbackId @Hooks before the virtual function.
The callback signature is `optional get_held_entity(Entity self)` ---@field set_post_get_held_entity fun(self, fun: fun(self: Entity): Entity?): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_held_entity(Entity self)` - ---@field set_pre_trigger_action fun(self, fun: fun(self: Entity, user: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) - ---@field set_post_trigger_action fun(self, fun: fun(self: Entity, user: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) + ---@field set_pre_trigger_action fun(self, fun: fun(self: Entity, user: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleporter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) + ---@field set_post_trigger_action fun(self, fun: fun(self: Entity, user: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleporter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) ---@field set_pre_activate fun(self, fun: fun(self: Entity, activator: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool activate(Entity self, Entity activator)`
Virtual function docs:
Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) ---@field set_post_activate fun(self, fun: fun(self: Entity, activator: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil activate(Entity self, Entity activator)`
Virtual function docs:
Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) ---@field set_pre_on_collision2 fun(self, fun: fun(self: Entity, other_entity: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool on_collision2(Entity self, Entity other_entity)`
Virtual function docs:
More like on_overlap, triggers when entities touch/overlap each other. Triggers for entities in it's EntityDB.collision2_mask @@ -2614,7 +2614,7 @@ function Entity:overlaps_with(rect_left, rect_bottom, rect_right, rect_top) end function Entity:overlaps_with(other) end ---Kill entity along with all entities attached to it. Be aware that for example killing push block with this function will also kill anything on top of it, any items, players, monsters etc. ---To avoid that, you can inclusively or exclusively limit certain MASK and ENT_TYPE. Note: the function will first check mask, if the entity doesn't match, it will look in the provided ENT_TYPE's ----destroy_corpse and responsible are the standard parameters for the kill funciton +---destroy_corpse and responsible are the standard parameters for the kill function ---@param destroy_corpse boolean ---@param responsible Entity ---@param mask integer? @@ -2686,7 +2686,7 @@ function Entity:destroy_recursive() end ---@field is_on_fire fun(self): boolean ---@field is_powerup_capable fun(self): boolean ---@field damage fun(self, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean @Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer - ---@field get_all_behaviors fun(self): integer[] @Get all avaible behavior ids + ---@field get_all_behaviors fun(self): integer[] @Get all available behavior ids ---@field set_behavior fun(self, behavior_id: integer): boolean @Set behavior, this is more than just state as it's an active function, for example climbing ladder is a behavior and it doesn't actually need ladder/rope entity
Returns false if entity doesn't have this behavior id ---@field get_behavior fun(self): integer @Get the current behavior id ---@field set_gravity fun(self, gravity: number): nil @Force the gravity for this entity. Will override anything set by special states like swimming too, unless you reset it. Default 1.0 @@ -2811,8 +2811,8 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field held_item ENT_TYPE @Used to transfer information to transition/next level. Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this ---@field held_item_metadata integer @Metadata of the held item (health, is cursed etc.)
Used to transfer information to transition/next level. Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this ---@field saved_pets_count integer - ---@field mount_type ENT_TYPE @Used to transfer information to transition/next level (player rading a mout). Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this - ---@field mount_metadata integer @Metadata of the mount (health, is cursed etc.)
Used to transfer information to transition/next level (player rading a mout). Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this + ---@field mount_type ENT_TYPE @Used to transfer information to transition/next level (player riding a mount). Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this + ---@field mount_metadata integer @Metadata of the mount (health, is cursed etc.)
Used to transfer information to transition/next level (player riding a mount). Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this ---@field kills_level integer ---@field kills_total integer ---@field collected_money_total integer @Total money collected during previous levels (so excluding the current one) @@ -2820,7 +2820,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field collected_money ENT_TYPE[] @size: 512 @Types of gold/gems collected during this level, used later to display during the transition ---@field collected_money_values integer[] @size: 512 @Values of gold/gems collected during this level, used later to display during the transition ---@field killed_enemies ENT_TYPE[] @size: 256 @Types of enemies killed during this level, used later to display during the transition - ---@field companion_count integer @Number of companions, it will determinate how many companions will be transfered to next level
Increments when player acquires new companion, decrements when one of them dies + ---@field companion_count integer @Number of companions, it will determinate how many companions will be transferred to next level
Increments when player acquires new companion, decrements when one of them dies ---@field companions ENT_TYPE[] @size: 8 @Used to transfer information to transition/next level. Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this ---@field companion_held_items ENT_TYPE[] @size: 8 @Used to transfer information to transition/next level. Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this ---@field companion_held_item_metadatas integer[] @size: 8 @Metadata of items held by companions (health, is cursed etc.)
Used to transfer information to transition/next level. Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this @@ -2838,7 +2838,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field last_state integer ---@field trust integer @Levels completed with, 0..3 ---@field whipped integer @Number of times whipped by player - ---@field walk_pause_timer integer @positive: walking, negative: wating/idle + ---@field walk_pause_timer integer @positive: walking, negative: waiting/idle ---@class Player : PowerupCapable ---@field inventory Inventory @@ -2868,7 +2868,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field deco_left integer ---@field deco_right integer ---@field fix_border_tile_animation fun(self): nil @Sets `animation_frame` of the floor for types `FLOOR_BORDERTILE`, `FLOOR_BORDERTILE_METAL` and `FLOOR_BORDERTILE_OCTOPUS`. - ---@field fix_decorations fun(self, fix_also_neighbors: boolean, fix_styled_floor: boolean): nil @Used to add decoration to a floor entity after it was spawned outside of level gen, is not necessary when spawning during level gen.
Set `fix_also_neighbours` to `true` to fix the neighbouring floor tile decorations on the border of the two tiles.
Set `fix_styled_floor` to `true` to fix decorations on `FLOORSTYLED_*` entities, those usually only have decorations when broken. + ---@field fix_decorations fun(self, fix_also_neighbors: boolean, fix_styled_floor: boolean): nil @Used to add decoration to a floor entity after it was spawned outside of level gen, is not necessary when spawning during level gen.
Set `fix_also_neighbors` to `true` to fix the neighboring floor tile decorations on the border of the two tiles.
Set `fix_styled_floor` to `true` to fix decorations on `FLOORSTYLED_*` entities, those usually only have decorations when broken. ---@field add_decoration fun(self, side: FLOOR_SIDE): nil @Explicitly add a decoration on the given side. Corner decorations only exist for `FLOOR_BORDERTILE` and `FLOOR_BORDERTILE_OCTOPUS`. ---@field remove_decoration fun(self, side: FLOOR_SIDE): nil @Explicitly remove a decoration on the given side. Corner decorations only exist for `FLOOR_BORDERTILE` and `FLOOR_BORDERTILE_OCTOPUS`. ---@field decorate_internal fun(self): nil @@ -3170,8 +3170,8 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field lose_interest_timer integer ---@field countdown_timer integer @can't shot when the timer is running ---@field is_patrolling boolean - ---@field aggro_trigger boolean @setting this makes him angry, if it's shopkeeper you get 2 agrro points - ---@field was_hurt boolean @also is set true if you set aggro to true, get's trigger even when whiping + ---@field aggro_trigger boolean @setting this makes him angry, if it's shopkeeper you get 2 aggro points + ---@field was_hurt boolean @also is set true if you set aggro to true, get's trigger even when whipping ---@class WalkingMonster : Monster ---@field chatting_to_uid integer @@ -3233,7 +3233,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field ceiling_pos_x number ---@field ceiling_pos_y number ---@field jump_timer integer @For the giant spider, some times he shot web instead of jumping - ---@field trigger_distance number @only in the x coord + ---@field trigger_distance number @only in the x coordinate ---@class HangSpider : Monster ---@field dangle_jump_timer integer @@ -3317,7 +3317,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field jump_pause_timer integer ---@field lava_detection_timer integer ---@field is_hot boolean - ---@field player_detect_state integer @0 - didnt_saw_player, 1 - saw_player, 2 - spited_lava; probably used so he won't spit imminently after seeing the player + ---@field player_detect_state integer @0 - didn't saw player, 1 - saw player, 2 - spited lava; probably used so he won't spit imminently after seeing the player ---@class Firebug : Monster ---@field sound SoundMeta @@ -3355,7 +3355,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field walk_pause_timer integer ---@class VanHorsing : NPC - ---@field show_text boolean @if set to true, he will say 'i've been hunting this fiend a long time!' when on screen + ---@field show_text boolean @if set to true, he will say "I've been hunting this fiend a long time!" when on screen ---@field special_message_shown boolean @one way door message has been shown ---@class WitchDoctor : WalkingMonster @@ -3390,7 +3390,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@class Octopus : WalkingMonster ---@class Bodyguard : NPC - ---@field position_state integer @0 - none, 1 - Tusk dice shop, 2 - Entrence to pleasure palace, 3 - Basement entrance to pleasure palace + ---@field position_state integer @0 - none, 1 - Tusk dice shop, 2 - Entrance to pleasure palace, 3 - Basement entrance to pleasure palace ---@field message_shown boolean ---@class Fish : Monster @@ -3416,7 +3416,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field climb_pause_timer integer ---@field shell_invincibility_timer integer ---@field monster_spawn_timer integer - ---@field initial_shell_health integer @excalibur wipes out immediately, bombs take off 11 points, when 0 vulnerable to whip + ---@field initial_shell_health integer @Excalibur wipes out immediately, bombs take off 11 points, when 0 vulnerable to whip ---@field player_seen_by_kingu boolean ---@class Anubis : Monster @@ -3622,7 +3622,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field snake_head_spawn_y number @This is custom variable, you need [activate_hundun_hack](#activate_hundun_hack) to use it ---@class HundunHead : Monster - ---@field attack_position_x number @Posiotion where the head will move on attack + ---@field attack_position_x number @Position where the head will move on attack ---@field attack_position_y number ---@field egg_crack_effect_uid integer ---@field targeted_player_uid integer @@ -3756,7 +3756,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@class DummyPurchasableEntity : Purchasable ---@class Bow : Purchasable - ---@field get_arrow_special_offset fun(self): number @When lain on the ground + ---@field get_arrow_special_offset fun(self): number @When lying on the ground ---@class Present : Purchasable ---@field inside ENT_TYPE @@ -4365,7 +4365,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field max_timer integer ---@field size number @Gets smaller as the timer gets close to the max_timer ----@class BGShopEntrence : Entity +---@class BGShopEntrance : Entity ---@field on_entering boolean ---@class BGFloatingDebris : BGSurfaceLayer @@ -4513,7 +4513,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@class EggplantThrower : Entity ---@class LogicalMiniGame : Entity - ---@field timer integer @Delay between spwning ufo + ---@field timer integer @Delay between spawning ufo ---@class DMSpawning : Entity ---@field spawn_x number @@ -4663,7 +4663,7 @@ function MovableBehavior:get_state_id() end ---@field spawn_decoration fun(self): nil @Spawns some specific decoration, e.g. Vlad's big banner ---@field spawn_decoration2 fun(self): nil @Spawns some other specific decorations, e.g. grass, flowers, udjat room decal ---@field spawn_extra fun(self): nil @Spawns specific extra entities and decorations, like gold key, seaweed, lanterns, banners, signs, wires... - ---@field do_procedural_spawn fun(self, info: SpawnInfo): nil @Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarb in dark levels etc.) + ---@field do_procedural_spawn fun(self, info: SpawnInfo): nil @Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarab in dark levels etc.) ---@field set_pre_virtual fun(self, entry: THEME_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. ---@field set_post_virtual fun(self, entry: THEME_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. @@ -4767,8 +4767,8 @@ function MovableBehavior:get_state_id() end ---@field set_post_spawn_decoration2 fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil spawn_decoration2(ThemeInfo self)`
Virtual function docs:
Spawns some other specific decorations, e.g. grass, flowers, udjat room decal ---@field set_pre_spawn_extra fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool spawn_extra(ThemeInfo self)`
Virtual function docs:
Spawns specific extra entities and decorations, like gold key, seaweed, lanterns, banners, signs, wires... ---@field set_post_spawn_extra fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil spawn_extra(ThemeInfo self)`
Virtual function docs:
Spawns specific extra entities and decorations, like gold key, seaweed, lanterns, banners, signs, wires... - ---@field set_pre_do_procedural_spawn fun(self, fun: fun(self: ThemeInfo, info: SpawnInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool do_procedural_spawn(ThemeInfo self, SpawnInfo info)`
Virtual function docs:
Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarb in dark levels etc.) - ---@field set_post_do_procedural_spawn fun(self, fun: fun(self: ThemeInfo, info: SpawnInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil do_procedural_spawn(ThemeInfo self, SpawnInfo info)`
Virtual function docs:
Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarb in dark levels etc.) + ---@field set_pre_do_procedural_spawn fun(self, fun: fun(self: ThemeInfo, info: SpawnInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool do_procedural_spawn(ThemeInfo self, SpawnInfo info)`
Virtual function docs:
Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarab in dark levels etc.) + ---@field set_post_do_procedural_spawn fun(self, fun: fun(self: ThemeInfo, info: SpawnInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil do_procedural_spawn(ThemeInfo self, SpawnInfo info)`
Virtual function docs:
Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarab in dark levels etc.) ---@class CustomTheme : ThemeInfo ---@field level_file string @Level file to load. Probably doesn't do much in custom themes, especially if you're forcing them in PRE_LOAD_LEVEL_FILES. @@ -5216,15 +5216,15 @@ function GuiDrawContext:win_pushid(id) end ---@class VanillaRenderContext ---@field draw_text_size fun(self, text: string, scale_x: number, scale_y: number, fontstyle: integer): number, number @Measure the provided text using the built-in renderer
If you can, consider creating your own TextRenderingInfo instead
You can then use `:text_size()` and `draw_text` with that one object
`draw_text_size` works by creating new TextRenderingInfo just to call `:text_size()`, which is not very optimal - ---@field set_corner_finish fun(self, c: CORNER_FINISH): nil @Set the prefered way of drawing corners for the non filled shapes + ---@field set_corner_finish fun(self, c: CORNER_FINISH): nil @Set the preferred way of drawing corners for the non filled shapes ---@field draw_screen_line fun(self, A: Vec2, B: Vec2, thickness: number, color: Color): nil @Draws a line on screen using the built-in renderer from point `A` to point `B`.
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events - ---@field draw_screen_rect fun(self, rect: AABB, thickness: number, color: Color, angle: number?, px: number?, py: number?): nil @Draw rectangle in screen coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc. (corner from the AABB, not the visible one from adding the `thickness`)
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events - ---@field draw_screen_rect_filled fun(self, rect: AABB, color: Color, angle: number?, px: number?, py: number?): nil @Draw filled rectangle in screen coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc.
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events + ---@field draw_screen_rect fun(self, rect: AABB, thickness: number, color: Color, angle: number?, px: number?, py: number?): nil @Draw rectangle in screen coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotation where 0,0 is center 1,1 is top right corner etc. (corner from the AABB, not the visible one from adding the `thickness`)
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events + ---@field draw_screen_rect_filled fun(self, rect: AABB, color: Color, angle: number?, px: number?, py: number?): nil @Draw filled rectangle in screen coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotation where 0,0 is center 1,1 is top right corner etc.
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events ---@field draw_screen_triangle fun(self, triangle: Triangle, thickness: number, color: Color): nil @Draw triangle in screen coordinates using the built-in renderer.
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events ---@field draw_screen_triangle_filled fun(self, triangle: Triangle, color: Color): nil @Draw filled triangle in screen coordinates using the built-in renderer.
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events ---@field draw_world_line fun(self, A: Vec2, B: Vec2, thickness: number, color: Color): nil @Draws a line in world coordinates using the built-in renderer from point `A` to point `B`.
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event - ---@field draw_world_rect fun(self, rect: AABB, thickness: number, color: Color, angle: number?, px: number?, py: number?): nil @Draw rectangle in world coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc. (corner from the AABB, not the visible one from adding the `thickness`)
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event - ---@field draw_world_rect_filled fun(self, rect: AABB, color: Color, angle: number?, px: number?, py: number?): nil @Draw rectangle in world coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc.
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event + ---@field draw_world_rect fun(self, rect: AABB, thickness: number, color: Color, angle: number?, px: number?, py: number?): nil @Draw rectangle in world coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotation where 0,0 is center 1,1 is top right corner etc. (corner from the AABB, not the visible one from adding the `thickness`)
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event + ---@field draw_world_rect_filled fun(self, rect: AABB, color: Color, angle: number?, px: number?, py: number?): nil @Draw rectangle in world coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotation where 0,0 is center 1,1 is top right corner etc.
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event ---@field draw_world_triangle fun(self, triangle: Triangle, thickness: number, color: Color): nil @Draw triangle in world coordinates using the built-in renderer.
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event ---@field draw_world_triangle_filled fun(self, triangle: Triangle, color: Color): nil @Draw filled triangle in world coordinates using the built-in renderer.
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event ---@field bounding_box AABB @@ -5267,7 +5267,7 @@ function VanillaRenderContext:draw_screen_texture(texture_id, row, column, left, ---@param color Color ---@return nil function VanillaRenderContext:draw_screen_texture(texture_id, row, column, rect, color) end ----Draw a texture in screen coordinates from top-left to bottom-right using the built-in renderer with angle, px/py is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc. +---Draw a texture in screen coordinates from top-left to bottom-right using the built-in renderer with angle, px/py is pivot for the rotation where 0,0 is center 1,1 is top right corner etc. ---Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events ---@param texture_id TEXTURE ---@param row integer @@ -5356,7 +5356,7 @@ function VanillaRenderContext:draw_world_texture(texture_id, row, column, left, ---@param color Color ---@return nil function VanillaRenderContext:draw_world_texture(texture_id, row, column, dest, color) end ----Draw a texture in world coordinates from top-left to bottom-right using the built-in renderer with angle, px/py is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc. +---Draw a texture in world coordinates from top-left to bottom-right using the built-in renderer with angle, px/py is pivot for the rotation where 0,0 is center 1,1 is top right corner etc. ---Use in combination with ON.RENDER_PRE_DRAW_DEPTH event ---For more control use the version taking a Quad instead ---@param texture_id TEXTURE @@ -5442,7 +5442,7 @@ function VanillaRenderContext:draw_world_poly_filled(points, color) end ---@field new any @constructors{} ---@field x number ---@field y number - ---@field destination_bottom_left_x number @destination is relative to the x,y centerpoint + ---@field destination_bottom_left_x number @destination is relative to the x,y center point ---@field destination_bottom_left_y number ---@field destination_bottom_right_x number ---@field destination_bottom_right_y number @@ -5475,12 +5475,12 @@ function VanillaRenderContext:draw_world_poly_filled(points, color) end ---@field new any @initializers(TextRenderingInfo_ctor, TextRenderingInfo_ctor2) ---@field x number ---@field y number - ---@field text_length integer @You can also just use `#` operator on the whole TextRenderingInfo to get the text lenght + ---@field text_length integer @You can also just use `#` operator on the whole TextRenderingInfo to get the text length ---@field width number ---@field height number - ---@field special_texture_id TEXTURE @Used to draw buttons and stuff, default is -1 wich uses the buttons texture - ---@field get_dest fun(self): Letter[] @Returns refrence to the letter coordinates relative to the x,y position - ---@field get_source fun(self): Letter[] @Returns refrence to the letter coordinates in the texture + ---@field special_texture_id TEXTURE @Used to draw buttons and stuff, default is -1 which uses the buttons texture + ---@field get_dest fun(self): Letter[] @Returns reference to the letter coordinates relative to the x,y position + ---@field get_source fun(self): Letter[] @Returns reference to the letter coordinates in the texture ---@field text_size fun(self): number, number @{width, height}, is only updated when you set/change the text. This is equivalent to draw_text_size ---@field rotate fun(self, angle: number, px: number?, py: number?): nil @Rotates the text around the pivot point (default 0), pivot is relative to the text position (x, y), use px and py to offset it ---@field set_text fun(self, text: string, scale_x: number, scale_y: number, alignment: VANILLA_TEXT_ALIGNMENT, fontstyle: VANILLA_FONT_STYLE): nil @Changes the text, only position stays the same, everything else (like rotation) is reset or set according to the parameters @@ -5505,7 +5505,7 @@ function VanillaRenderContext:draw_world_poly_filled(points, color) end ---@class HudElement ---@field dim boolean @Hide background and dim if using the auto adjust setting. ---@field opacity number @Background will be drawn if this is not 0.5 - ---@field time_dim integer @Level time when element should dim again after hilighted, INT_MAX if dimmed on auto adjust. 0 on opaque. + ---@field time_dim integer @Level time when element should dim again after highlighted, INT_MAX if dimmed on auto adjust. 0 on opaque. ---@class HudPlayer : HudElement ---@field health integer @@ -5574,7 +5574,7 @@ function VanillaRenderContext:draw_world_poly_filled(points, color) end ---@class Vec2 ---@field x number ---@field y number - ---@field distance_to fun(self, other: Vec2): number @Just simple pythagoras theorem + ---@field distance_to fun(self, other: Vec2): number @Just simple Pythagoras theorem ---@field set fun(self, other: Vec2): Vec2 ---@field split fun(self): number, number local Vec2 = nil @@ -5664,7 +5664,7 @@ function Triangle:is_point_inside(x, y, epsilon) end ---@field top_left_x number ---@field top_left_y number ---@field get_AABB fun(self): AABB @Returns the max/min values of the Quad - ---@field rotate fun(self, angle: number, px: number, py: number): Quad @Rotates a Quad by an angle, px/py are not offsets, use `:get_AABB():center()` to get approximated center for simetrical quadrangle + ---@field rotate fun(self, angle: number, px: number, py: number): Quad @Rotates a Quad by an angle, px/py are not offsets, use `:get_AABB():center()` to get approximated center for symmetrical quadrangle ---@field flip_horizontally fun(self): Quad ---@field flip_vertically fun(self): Quad ---@field set fun(self, other: Quad): Quad @@ -6116,7 +6116,7 @@ function Quad:is_point_inside(x, y, epsilon) end ---@field fade_timer integer ---@field page_timer integer ---@field opacity number - ---@field pages JournalPage[] @Stores pages loaded into memeory. It's not cleared after the journal is closed or when you go back to the main (menu) page.
Use `:get_type()` to chcek page type and cast it correctly (see ON.[RENDER_PRE_JOURNAL_PAGE](#ON-RENDER_PRE_JOURNAL_PAGE)) + ---@field pages JournalPage[] @Stores pages loaded into memory. It's not cleared after the journal is closed or when you go back to the main (menu) page.
Use `:get_type()` to check page type and cast it correctly (see ON.[RENDER_PRE_JOURNAL_PAGE](#ON-RENDER_PRE_JOURNAL_PAGE)) ---@class JournalPage ---@field background TextureRenderingInfo diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 22a811152..1099f5cc9 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -320,14 +320,14 @@ nil | [draw_text(TextRenderingInfo tri, Color color)](https://github.com/spelunk tuple<float, float> | [draw_text_size(string text, float scale_x, float scale_y, int fontstyle)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_text_size) | Measure the provided text using the built-in renderer
If you can, consider creating your own [TextRenderingInfo](#TextRenderingInfo) instead
You can then use `:text_size()` and `draw_text` with that one object
`draw_text_size` works by creating new TextRenderingInfo just to call `:text_size()`, which is not very optimal nil | [draw_screen_texture(TEXTURE texture_id, int row, int column, float left, float top, float right, float bottom, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_texture) | Draw a texture in screen coordinates from top-left to bottom-right using the built-in renderer
Use in combination with [ON](#ON).RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events nil | [draw_screen_texture(TEXTURE texture_id, int row, int column, AABB rect, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_texture) | Draw a texture in screen coordinates from top-left to bottom-right using the built-in renderer
Use in combination with [ON](#ON).RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events -nil | [draw_screen_texture(TEXTURE texture_id, int row, int column, AABB rect, Color color, float angle, float px, float py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_texture) | Draw a texture in screen coordinates from top-left to bottom-right using the built-in renderer with angle, px/py is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc.
Use in combination with [ON](#ON).RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events +nil | [draw_screen_texture(TEXTURE texture_id, int row, int column, AABB rect, Color color, float angle, float px, float py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_texture) | Draw a texture in screen coordinates from top-left to bottom-right using the built-in renderer with angle, px/py is pivot for the rotation where 0,0 is center 1,1 is top right corner etc.
Use in combination with [ON](#ON).RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events nil | [draw_screen_texture(TEXTURE texture_id, int row, int column, Quad dest, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_texture) | Draw a texture in screen coordinates from top-left to bottom-right using the built-in renderer
Use in combination with [ON](#ON).RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events nil | [draw_screen_texture(TEXTURE texture_id, Quad source, Quad dest, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_texture) | Draw a texture in screen coordinates from top-left to bottom-right using the built-in renderer. `source` - the coordinates in the texture, `dest` - the coordinates on the screen
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events nil | [draw_screen_texture(TEXTURE texture_id, TextureRenderingInfo tri, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_texture) | Draw a texture in screen coordinates using [TextureRenderingInfo](#TextureRenderingInfo)
Use in combination with [ON](#ON).RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events -nil | [set_corner_finish(CORNER_FINISH c)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_corner_finish) | Set the prefered way of drawing corners for the non filled shapes +nil | [set_corner_finish(CORNER_FINISH c)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_corner_finish) | Set the preferred way of drawing corners for the non filled shapes nil | [draw_screen_line(Vec2 A, Vec2 B, float thickness, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_line) | Draws a line on screen using the built-in renderer from point `A` to point `B`.
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events -nil | [draw_screen_rect(AABB rect, float thickness, Color color, optional angle, optional px, optional py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_rect) | Draw rectangle in screen coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc. (corner from the AABB, not the visible one from adding the `thickness`)
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events -nil | [draw_screen_rect_filled(AABB rect, Color color, optional angle, optional px, optional py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_rect_filled) | Draw filled rectangle in screen coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc.
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events +nil | [draw_screen_rect(AABB rect, float thickness, Color color, optional angle, optional px, optional py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_rect) | Draw rectangle in screen coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotation where 0,0 is center 1,1 is top right corner etc. (corner from the AABB, not the visible one from adding the `thickness`)
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events +nil | [draw_screen_rect_filled(AABB rect, Color color, optional angle, optional px, optional py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_rect_filled) | Draw filled rectangle in screen coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotation where 0,0 is center 1,1 is top right corner etc.
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events nil | [draw_screen_triangle(Triangle triangle, float thickness, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_triangle) | Draw triangle in screen coordinates using the built-in renderer.
Use in combination with [ON](#ON).RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events nil | [draw_screen_triangle_filled(Triangle triangle, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_triangle_filled) | Draw filled triangle in screen coordinates using the built-in renderer.
Use in combination with [ON](#ON).RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events nil | [draw_screen_poly(array points, float thickness, Color color, bool closed)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_poly) | Draw a polyline on screen from points using the built-in renderer
Draws from the first to the last point, use `closed` to connect first and last as well
Use in combination with ON.RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events @@ -336,14 +336,14 @@ nil | [draw_screen_poly_filled(array points, Color color)](https://github. nil | [draw_screen_poly_filled(Quad points, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_screen_poly_filled) | Draw filled quadrilateral in screen coordinates from top-left to bottom-right using the built-in renderer.
Use in combination with [ON](#ON).RENDER_✱_HUD/PAUSE_MENU/JOURNAL_PAGE events nil | [draw_world_texture(TEXTURE texture_id, int row, int column, float left, float top, float right, float bottom, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_texture) | Draw a texture in world coordinates from top-left to bottom-right using the built-in renderer
Use in combination with [ON](#ON).RENDER_PRE_DRAW_DEPTH event
For more control use the version taking a [Quad](#Quad) instead nil | [draw_world_texture(TEXTURE texture_id, int row, int column, AABB dest, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_texture) | Draw a texture in world coordinates from top-left to bottom-right using the built-in renderer
Use in combination with [ON](#ON).RENDER_PRE_DRAW_DEPTH event
For more control use the version taking a [Quad](#Quad) instead -nil | [draw_world_texture(TEXTURE texture_id, int row, int column, AABB dest, Color color, float angle, float px, float py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_texture) | Draw a texture in world coordinates from top-left to bottom-right using the built-in renderer with angle, px/py is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc.
Use in combination with [ON](#ON).RENDER_PRE_DRAW_DEPTH event
For more control use the version taking a [Quad](#Quad) instead +nil | [draw_world_texture(TEXTURE texture_id, int row, int column, AABB dest, Color color, float angle, float px, float py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_texture) | Draw a texture in world coordinates from top-left to bottom-right using the built-in renderer with angle, px/py is pivot for the rotation where 0,0 is center 1,1 is top right corner etc.
Use in combination with [ON](#ON).RENDER_PRE_DRAW_DEPTH event
For more control use the version taking a [Quad](#Quad) instead nil | [draw_world_texture(TEXTURE texture_id, int row, int column, Quad dest, Color color, WORLD_SHADER shader)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_texture) | Draw a texture in world coordinates from top-left to bottom-right using the built-in renderer
The `shader` parameter controls how to render the texture
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event nil | [draw_world_texture(TEXTURE texture_id, int row, int column, Quad dest, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_texture) | Draw a texture in world coordinates from top-left to bottom-right using the built-in renderer
Use in combination with [ON](#ON).RENDER_PRE_DRAW_DEPTH event nil | [draw_world_texture(TEXTURE texture_id, Quad source, Quad dest, Color color, WORLD_SHADER shader)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_texture) | Draw a texture in world coordinates from top-left to bottom-right using the built-in renderer. `source` - the coordinates in the texture, `dest` - the coordinates on the screen
The `shader` parameter controls how to render the texture
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event nil | [draw_world_texture(TEXTURE texture_id, Quad source, Quad dest, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_texture) | Draw a texture in world coordinates from top-left to bottom-right using the built-in renderer. `source` - the coordinates in the texture, `dest` - the coordinates on the screen
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event nil | [draw_world_line(Vec2 A, Vec2 B, float thickness, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_line) | Draws a line in world coordinates using the built-in renderer from point `A` to point `B`.
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event -nil | [draw_world_rect(AABB rect, float thickness, Color color, optional angle, optional px, optional py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_rect) | Draw rectangle in world coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc. (corner from the AABB, not the visible one from adding the `thickness`)
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event -nil | [draw_world_rect_filled(AABB rect, Color color, optional angle, optional px, optional py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_rect_filled) | Draw rectangle in world coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotatnion where 0,0 is center 1,1 is top right corner etc.
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event +nil | [draw_world_rect(AABB rect, float thickness, Color color, optional angle, optional px, optional py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_rect) | Draw rectangle in world coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotation where 0,0 is center 1,1 is top right corner etc. (corner from the AABB, not the visible one from adding the `thickness`)
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event +nil | [draw_world_rect_filled(AABB rect, Color color, optional angle, optional px, optional py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_rect_filled) | Draw rectangle in world coordinates from top-left to bottom-right using the built-in renderer with optional `angle`.
`px`/`py` is pivot for the rotation where 0,0 is center 1,1 is top right corner etc.
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event nil | [draw_world_triangle(Triangle triangle, float thickness, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_triangle) | Draw triangle in world coordinates using the built-in renderer.
Use in combination with [ON](#ON).RENDER_PRE_DRAW_DEPTH event nil | [draw_world_triangle_filled(Triangle triangle, Color color)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_triangle_filled) | Draw filled triangle in world coordinates using the built-in renderer.
Use in combination with [ON](#ON).RENDER_PRE_DRAW_DEPTH event nil | [draw_world_poly(array points, float thickness, Color color, bool closed)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_world_poly) | Draw a polyline in world coordinates from points using the built-in renderer
Draws from the first to the last point, use `closed` to connect first and last as well
Use in combination with ON.RENDER_PRE_DRAW_DEPTH event @@ -369,7 +369,7 @@ int | [state](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=state) | int | [last_state](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=last_state) | int | [trust](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=trust) | Levels completed with, 0..3 int | [whipped](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=whipped) | Number of times whipped by player -int | [walk_pause_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=walk_pause_timer) | positive: walking, negative: wating/idle +int | [walk_pause_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=walk_pause_timer) | positive: walking, negative: waiting/idle ### Animation @@ -525,8 +525,8 @@ int | [time_of_death](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=t [ENT_TYPE](#ENT_TYPE) | [held_item](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=held_item) | Used to transfer information to transition/next level. Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this int | [held_item_metadata](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=held_item_metadata) | Metadata of the held item (health, is cursed etc.)
Used to transfer information to transition/next level. Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this int | [saved_pets_count](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=saved_pets_count) | -[ENT_TYPE](#ENT_TYPE) | [mount_type](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=mount_type) | Used to transfer information to transition/next level (player rading a mout). Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this -int | [mount_metadata](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=mount_metadata) | Metadata of the mount (health, is cursed etc.)
Used to transfer information to transition/next level (player rading a mout). Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this +[ENT_TYPE](#ENT_TYPE) | [mount_type](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=mount_type) | Used to transfer information to transition/next level (player riding a mount). Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this +int | [mount_metadata](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=mount_metadata) | Metadata of the mount (health, is cursed etc.)
Used to transfer information to transition/next level (player riding a mount). Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this int | [kills_level](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=kills_level) | int | [kills_total](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=kills_total) | int | [collected_money_total](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collected_money_total) | Total money collected during previous levels (so excluding the current one) @@ -534,7 +534,7 @@ int | [collected_money_count](https://github.com/spelunky-fyi/overlunky/search?l array<[ENT_TYPE](#ENT_TYPE), 512> | [collected_money](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collected_money) | Types of gold/gems collected during this level, used later to display during the transition array<int, 512> | [collected_money_values](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collected_money_values) | Values of gold/gems collected during this level, used later to display during the transition array<[ENT_TYPE](#ENT_TYPE), 256> | [killed_enemies](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=killed_enemies) | Types of enemies killed during this level, used later to display during the transition -int | [companion_count](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=companion_count) | Number of companions, it will determinate how many companions will be transfered to next level
Increments when player acquires new companion, decrements when one of them dies +int | [companion_count](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=companion_count) | Number of companions, it will determinate how many companions will be transferred to next level
Increments when player acquires new companion, decrements when one of them dies array<[ENT_TYPE](#ENT_TYPE), 8> | [companions](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=companions) | Used to transfer information to transition/next level. Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this array<[ENT_TYPE](#ENT_TYPE), 8> | [companion_held_items](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=companion_held_items) | Used to transfer information to transition/next level. Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this array<int, 8> | [companion_held_item_metadatas](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=companion_held_item_metadatas) | Metadata of items held by companions (health, is cursed etc.)
Used to transfer information to transition/next level. Is not updated during a level
You can use `ON.PRE_LEVEL_GENERATION` to access/edit this @@ -747,7 +747,7 @@ Type | Name | Description ---- | ---- | ----------- bool | [dim](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=dim) | Hide background and dim if using the auto adjust setting. float | [opacity](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=opacity) | Background will be drawn if this is not 0.5 -int | [time_dim](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=time_dim) | Level time when element should dim again after hilighted, INT_MAX if dimmed on auto adjust. 0 on opaque. +int | [time_dim](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=time_dim) | Level time when element should dim again after highlighted, INT_MAX if dimmed on auto adjust. 0 on opaque. ### HudMoney @@ -910,7 +910,7 @@ float | [top_left_y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=to [AABB](#AABB) | [get_AABB()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_AABB) | Returns the max/min values of the [Quad](#Quad) [Quad](#Quad) | [offset(Vec2 off)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=offset) | [Quad](#Quad) | [offset(float off_x, float off_y)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=offset) | -[Quad](#Quad) | [rotate(float angle, float px, float py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=rotate) | Rotates a [Quad](#Quad) by an angle, px/py are not offsets, use `:get_AABB():center()` to get approximated center for simetrical quadrangle +[Quad](#Quad) | [rotate(float angle, float px, float py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=rotate) | Rotates a [Quad](#Quad) by an angle, px/py are not offsets, use `:get_AABB():center()` to get approximated center for symmetrical quadrangle [Quad](#Quad) | [flip_horizontally()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=flip_horizontally) | [Quad](#Quad) | [flip_vertically()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=flip_vertically) | bool | [is_point_inside(Vec2 p, optional epsilon)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_point_inside) | Check if point lies inside of triangle
Because of the imprecise nature of floating point values, the `epsilon` value is needed to compare the floats, the default value is `0.00001` @@ -1072,7 +1072,7 @@ float | [x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=x) | float | [y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=y) | [Vec2](#Vec2) | [rotate(float angle, float px, float py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=rotate) | [Vec2](#Vec2) | [rotate(float angle, Vec2 p)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=rotate) | -float | [distance_to(Vec2 other)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=distance_to) | Just simple pythagoras theorem +float | [distance_to(Vec2 other)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=distance_to) | Just simple Pythagoras theorem [Vec2](#Vec2) | [set(Vec2 other)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set) | tuple<float, float> | [split()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=split) | @@ -1410,7 +1410,7 @@ array<int, 17> | [level_config](https://github.com/spelunky-fyi/overlunky/ ### Illumination -Generic obcject for lights in the game, you can make your own with [create_illumination](#create_illumination)
+Generic object for lights in the game, you can make your own with [create_illumination](#create_illumination)
Used in [StateMemory](#StateMemory), [Player](#Player), [PlayerGhost](#PlayerGhost), [BurningRopeEffect](#BurningRopeEffect) ... Type | Name | Description @@ -1996,7 +1996,7 @@ int | [max_page_count](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q= int | [fade_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=fade_timer) | int | [page_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=page_timer) | float | [opacity](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=opacity) | -vector<[JournalPage](#JournalPage)> | [pages](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=pages) | Stores pages loaded into memeory. It's not cleared after the journal is closed or when you go back to the main (menu) page.
Use `:get_type()` to chcek page type and cast it correctly (see ON.[RENDER_PRE_JOURNAL_PAGE](#ON-RENDER_PRE_JOURNAL_PAGE)) +vector<[JournalPage](#JournalPage)> | [pages](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=pages) | Stores pages loaded into memory. It's not cleared after the journal is closed or when you go back to the main (menu) page.
Use `:get_type()` to check page type and cast it correctly (see ON.[RENDER_PRE_JOURNAL_PAGE](#ON-RENDER_PRE_JOURNAL_PAGE)) ### MenuScreenPanels @@ -3128,12 +3128,12 @@ Type | Name | Description | [new](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=new) | [TextRenderingInfo](#TextRenderingInfo):new(string text, float scale_x, float scale_y, [VANILLA_TEXT_ALIGNMENT](#VANILLA_TEXT_ALIGNMENT) alignment, [VANILLA_FONT_STYLE](#VANILLA_FONT_STYLE) fontstyle)
[TextRenderingInfo](#TextRenderingInfo):new(string text, float x, float y, float scale_x, float scale_y, [VANILLA_TEXT_ALIGNMENT](#VANILLA_TEXT_ALIGNMENT) alignment, [VANILLA_FONT_STYLE](#VANILLA_FONT_STYLE) fontstyle)
Creates new [TextRenderingInfo](#TextRenderingInfo) that can be used in [VanillaRenderContext](#VanillaRenderContext) draw_text
For static text, it is better to use one object and call draw_text with it, instead of relaying on draw_text creating this object for you
float | [x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=x) | float | [y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=y) | -int | [text_length](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=text_length) | You can also just use `#` operator on the whole TextRenderingInfo to get the text lenght +int | [text_length](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=text_length) | You can also just use `#` operator on the whole TextRenderingInfo to get the text length float | [width](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=width) | float | [height](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=height) | -[TEXTURE](#TEXTURE) | [special_texture_id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=special_texture_id) | Used to draw buttons and stuff, default is -1 wich uses the buttons texture -span<[Letter](#Letter)> | [get_dest()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_dest) | Returns refrence to the letter coordinates relative to the x,y position -span<[Letter](#Letter)> | [get_source()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_source) | Returns refrence to the letter coordinates in the texture +[TEXTURE](#TEXTURE) | [special_texture_id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=special_texture_id) | Used to draw buttons and stuff, default is -1 which uses the buttons texture +span<[Letter](#Letter)> | [get_dest()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_dest) | Returns reference to the letter coordinates relative to the x,y position +span<[Letter](#Letter)> | [get_source()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_source) | Returns reference to the letter coordinates in the texture tuple<float, float> | [text_size()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=text_size) | {width, height}, is only updated when you set/change the text. This is equivalent to draw_text_size nil | [rotate(float angle, optional px, optional py)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=rotate) | Rotates the text around the pivot point (default 0), pivot is relative to the text position (x, y), use px and py to offset it nil | [set_text(string text, float scale_x, float scale_y, VANILLA_TEXT_ALIGNMENT alignment, VANILLA_FONT_STYLE fontstyle)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_text) | Changes the text, only position stays the same, everything else (like rotation) is reset or set according to the parameters @@ -3168,7 +3168,7 @@ Type | Name | Description | [new](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=new) | float | [x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=x) | float | [y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=y) | -float | [destination_bottom_left_x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destination_bottom_left_x) | destination is relative to the x,y centerpoint +float | [destination_bottom_left_x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destination_bottom_left_x) | destination is relative to the x,y center point float | [destination_bottom_left_y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destination_bottom_left_y) | float | [destination_bottom_right_x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destination_bottom_right_x) | float | [destination_bottom_right_y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destination_bottom_right_y) | @@ -3397,7 +3397,7 @@ int | [get_shop_chance()](https://github.com/spelunky-fyi/overlunky/search?l=Lua nil | [spawn_decoration()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_decoration) | Spawns some specific decoration, e.g. [Vlad](#Vlad)'s big banner nil | [spawn_decoration2()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_decoration2) | Spawns some other specific decorations, e.g. grass, flowers, udjat room decal nil | [spawn_extra()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_extra) | Spawns specific extra entities and decorations, like gold key, seaweed, lanterns, banners, signs, wires... -nil | [do_procedural_spawn(SpawnInfo info)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=do_procedural_spawn) | Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarb in dark levels etc.) +nil | [do_procedural_spawn(SpawnInfo info)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=do_procedural_spawn) | Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarab in dark levels etc.) [CallbackId](#Aliases) | [set_pre_virtual(THEME_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. [CallbackId](#Aliases) | [set_post_virtual(THEME_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. @@ -3501,8 +3501,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_spawn_decoration2(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_spawn_decoration2) | Hooks after the virtual function.
The callback signature is `nil spawn_decoration2(ThemeInfo self)`
Virtual function docs:
Spawns some other specific decorations, e.g. grass, flowers, udjat room decal [CallbackId](#Aliases) | [set_pre_spawn_extra(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_spawn_extra) | Hooks before the virtual function.
The callback signature is `bool spawn_extra(ThemeInfo self)`
Virtual function docs:
Spawns specific extra entities and decorations, like gold key, seaweed, lanterns, banners, signs, wires... [CallbackId](#Aliases) | [set_post_spawn_extra(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_spawn_extra) | Hooks after the virtual function.
The callback signature is `nil spawn_extra(ThemeInfo self)`
Virtual function docs:
Spawns specific extra entities and decorations, like gold key, seaweed, lanterns, banners, signs, wires... -[CallbackId](#Aliases) | [set_pre_do_procedural_spawn(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_do_procedural_spawn) | Hooks before the virtual function.
The callback signature is `bool do_procedural_spawn(ThemeInfo self, SpawnInfo info)`
Virtual function docs:
Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarb in dark levels etc.) -[CallbackId](#Aliases) | [set_post_do_procedural_spawn(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_do_procedural_spawn) | Hooks after the virtual function.
The callback signature is `nil do_procedural_spawn(ThemeInfo self, SpawnInfo info)`
Virtual function docs:
Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarb in dark levels etc.) +[CallbackId](#Aliases) | [set_pre_do_procedural_spawn(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_do_procedural_spawn) | Hooks before the virtual function.
The callback signature is `bool do_procedural_spawn(ThemeInfo self, SpawnInfo info)`
Virtual function docs:
Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarab in dark levels etc.) +[CallbackId](#Aliases) | [set_post_do_procedural_spawn(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_do_procedural_spawn) | Hooks after the virtual function.
The callback signature is `nil do_procedural_spawn(ThemeInfo self, SpawnInfo info)`
Virtual function docs:
Spawns a single procedural entity, used in spawn_procedural (mostly monsters, scarab in dark levels etc.) # Entity types @@ -3578,7 +3578,7 @@ int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | int | [max_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=max_timer) | float | [size](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=size) | Gets smaller as the timer gets close to the max_timer -### BGShopEntrence +### BGShopEntrance Derived from [Entity](#Entity) @@ -3855,7 +3855,7 @@ int | [deco_bottom](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=dec int | [deco_left](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=deco_left) | int | [deco_right](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=deco_right) | nil | [fix_border_tile_animation()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=fix_border_tile_animation) | Sets `animation_frame` of the floor for types `FLOOR_BORDERTILE`, `FLOOR_BORDERTILE_METAL` and `FLOOR_BORDERTILE_OCTOPUS`. -nil | [fix_decorations(bool fix_also_neighbors, bool fix_styled_floor)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=fix_decorations) | Used to add decoration to a floor entity after it was spawned outside of level gen, is not necessary when spawning during level gen.
Set `fix_also_neighbours` to `true` to fix the neighbouring floor tile decorations on the border of the two tiles.
Set `fix_styled_floor` to `true` to fix decorations on `FLOORSTYLED_*` entities, those usually only have decorations when broken. +nil | [fix_decorations(bool fix_also_neighbors, bool fix_styled_floor)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=fix_decorations) | Used to add decoration to a floor entity after it was spawned outside of level gen, is not necessary when spawning during level gen.
Set `fix_also_neighbors` to `true` to fix the neighboring floor tile decorations on the border of the two tiles.
Set `fix_styled_floor` to `true` to fix decorations on `FLOORSTYLED_*` entities, those usually only have decorations when broken. nil | [add_decoration(FLOOR_SIDE side)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=add_decoration) | Explicitly add a decoration on the given side. Corner decorations only exist for `FLOOR_BORDERTILE` and `FLOOR_BORDERTILE_OCTOPUS`. nil | [remove_decoration(FLOOR_SIDE side)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=remove_decoration) | Explicitly remove a decoration on the given side. Corner decorations only exist for `FLOOR_BORDERTILE` and `FLOOR_BORDERTILE_OCTOPUS`. nil | [decorate_internal()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=decorate_internal) | @@ -4244,14 +4244,14 @@ nil | [kill(bool destroy_corpse, Entity responsible)](https://github.com/spelunk nil | [destroy()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destroy) | Completely removes the entity from existence nil | [activate(Entity activator)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=activate) | Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) nil | [perform_teleport(int delta_x, int delta_y)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=perform_teleport) | Performs a teleport as if the entity had a teleporter and used it. The delta coordinates are where you want the entity to teleport to relative to its current position, in tiles (so integers, not floats). Positive numbers = to the right and up, negative left and down. -bool | [trigger_action(Entity user)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=trigger_action) | Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) +bool | [trigger_action(Entity user)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=trigger_action) | Triggers weapons and other held items like teleporter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) int | [get_metadata()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_metadata) | e.g. for turkey: stores health, poison/curse state, for mattock: remaining swings (returned value is transferred) nil | [apply_metadata(int metadata)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apply_metadata) | nil | [set_invisible(bool value)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_invisible) | vector<int> | [get_items()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_items) | bool | [is_in_liquid()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_in_liquid) | Returns true if entity is in water/lava bool | [is_cursed()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_cursed) | -nil | [kill_recursive(bool destroy_corpse, Entity responsible, optional mask, array ent_types, RECURSIVE_MODE rec_mode)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=kill_recursive) | Kill entity along with all entities attached to it. Be aware that for example killing push block with this function will also kill anything on top of it, any items, players, monsters etc.
To avoid that, you can inclusively or exclusively limit certain [MASK](#MASK) and [ENT_TYPE](#ENT_TYPE). Note: the function will first check mask, if the entity doesn't match, it will look in the provided [ENT_TYPE](#ENT_TYPE)'s
destroy_corpse and responsible are the standard parameters for the kill funciton +nil | [kill_recursive(bool destroy_corpse, Entity responsible, optional mask, array ent_types, RECURSIVE_MODE rec_mode)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=kill_recursive) | Kill entity along with all entities attached to it. Be aware that for example killing push block with this function will also kill anything on top of it, any items, players, monsters etc.
To avoid that, you can inclusively or exclusively limit certain [MASK](#MASK) and [ENT_TYPE](#ENT_TYPE). Note: the function will first check mask, if the entity doesn't match, it will look in the provided [ENT_TYPE](#ENT_TYPE)'s
destroy_corpse and responsible are the standard parameters for the kill function nil | [kill_recursive(bool destroy_corpse, Entity responsible)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=kill_recursive) | Short for using [RECURSIVE_MODE](#RECURSIVE_MODE).NONE nil | [destroy_recursive(optional mask, array ent_types, RECURSIVE_MODE rec_mode)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destroy_recursive) | Destroy entity along with all entities attached to it. Be aware that for example destroying push block with this function will also destroy anything on top of it, any items, players, monsters etc.
To avoid that, you can inclusively or exclusively limit certain [MASK](#MASK) and [ENT_TYPE](#ENT_TYPE). Note: the function will first check the mask, if the entity doesn't match, it will look in the provided [ENT_TYPE](#ENT_TYPE)'s nil | [destroy_recursive()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destroy_recursive) | Short for using [RECURSIVE_MODE](#RECURSIVE_MODE).NONE @@ -4295,8 +4295,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_remove_item(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_remove_item) | Hooks after the virtual function.
The callback signature is `nil remove_item(Entity self, Entity entity, bool autokill_check)` [CallbackId](#Aliases) | [set_pre_get_held_entity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_held_entity) | Hooks before the virtual function.
The callback signature is `optional get_held_entity(Entity self)` [CallbackId](#Aliases) | [set_post_get_held_entity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_held_entity) | Hooks after the virtual function.
The callback signature is `nil get_held_entity(Entity self)` -[CallbackId](#Aliases) | [set_pre_trigger_action(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_trigger_action) | Hooks before the virtual function.
The callback signature is `optional trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) -[CallbackId](#Aliases) | [set_post_trigger_action(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_trigger_action) | Hooks after the virtual function.
The callback signature is `nil trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) +[CallbackId](#Aliases) | [set_pre_trigger_action(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_trigger_action) | Hooks before the virtual function.
The callback signature is `optional trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleporter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) +[CallbackId](#Aliases) | [set_post_trigger_action(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_trigger_action) | Hooks after the virtual function.
The callback signature is `nil trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleporter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) [CallbackId](#Aliases) | [set_pre_activate(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_activate) | Hooks before the virtual function.
The callback signature is `bool activate(Entity self, Entity activator)`
Virtual function docs:
Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) [CallbackId](#Aliases) | [set_post_activate(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_activate) | Hooks after the virtual function.
The callback signature is `nil activate(Entity self, Entity activator)`
Virtual function docs:
Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) [CallbackId](#Aliases) | [set_pre_on_collision2(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_on_collision2) | Hooks before the virtual function.
The callback signature is `bool on_collision2(Entity self, Entity other_entity)`
Virtual function docs:
More like on_overlap, triggers when entities touch/overlap each other. Triggers for entities in it's EntityDB.collision2_mask @@ -4523,7 +4523,7 @@ Derived from [Entity](#Entity) Type | Name | Description ---- | ---- | ----------- -int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | Delay between spwning ufo +int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | Delay between spawning ufo ### LogicalRegeneratingBlock @@ -4678,7 +4678,7 @@ Derived from [Entity](#Entity) [Movable](#Movable) [PowerupCapable](#PowerupCapa Type | Name | Description ---- | ---- | ----------- -int | [position_state](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=position_state) | 0 - none, 1 - Tusk dice shop, 2 - Entrence to pleasure palace, 3 - Basement entrance to pleasure palace +int | [position_state](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=position_state) | 0 - none, 1 - Tusk dice shop, 2 - Entrance to pleasure palace, 3 - Basement entrance to pleasure palace bool | [message_shown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=message_shown) | ### CatMummy @@ -5117,7 +5117,7 @@ Derived from [Entity](#Entity) [Movable](#Movable) [PowerupCapable](#PowerupCapa Type | Name | Description ---- | ---- | ----------- -float | [attack_position_x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=attack_position_x) | Posiotion where the head will move on attack +float | [attack_position_x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=attack_position_x) | Position where the head will move on attack float | [attack_position_y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=attack_position_y) | int | [egg_crack_effect_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=egg_crack_effect_uid) | int | [targeted_player_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=targeted_player_uid) | @@ -5169,7 +5169,7 @@ float | [climb_direction_y](https://github.com/spelunky-fyi/overlunky/search?l=L int | [climb_pause_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=climb_pause_timer) | int | [shell_invincibility_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=shell_invincibility_timer) | int | [monster_spawn_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=monster_spawn_timer) | -int | [initial_shell_health](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=initial_shell_health) | excalibur wipes out immediately, bombs take off 11 points, when 0 vulnerable to whip +int | [initial_shell_health](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=initial_shell_health) | [Excalibur](#Excalibur) wipes out immediately, bombs take off 11 points, when 0 vulnerable to whip bool | [player_seen_by_kingu](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_seen_by_kingu) | ### Lahamu @@ -5211,7 +5211,7 @@ int | [shoot_lava_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua& int | [jump_pause_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=jump_pause_timer) | int | [lava_detection_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=lava_detection_timer) | bool | [is_hot](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_hot) | -int | [player_detect_state](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_detect_state) | 0 - didnt_saw_player, 1 - saw_player, 2 - spited_lava; probably used so he won't spit imminently after seeing the player +int | [player_detect_state](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_detect_state) | 0 - didn't saw player, 1 - saw player, 2 - spited lava; probably used so he won't spit imminently after seeing the player ### Leprechaun @@ -5550,8 +5550,8 @@ int | [patrol_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=pa int | [lose_interest_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=lose_interest_timer) | int | [countdown_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=countdown_timer) | can't shot when the timer is running bool | [is_patrolling](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_patrolling) | -bool | [aggro_trigger](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=aggro_trigger) | setting this makes him angry, if it's shopkeeper you get 2 agrro points -bool | [was_hurt](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=was_hurt) | also is set true if you set aggro to true, get's trigger even when whiping +bool | [aggro_trigger](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=aggro_trigger) | setting this makes him angry, if it's shopkeeper you get 2 aggro points +bool | [was_hurt](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=was_hurt) | also is set true if you set aggro to true, get's trigger even when whipping ### Scarab @@ -5620,7 +5620,7 @@ Type | Name | Description float | [ceiling_pos_x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ceiling_pos_x) | float | [ceiling_pos_y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ceiling_pos_y) | int | [jump_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=jump_timer) | For the giant spider, some times he shot web instead of jumping -float | [trigger_distance](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=trigger_distance) | only in the x coord +float | [trigger_distance](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=trigger_distance) | only in the x coordinate ### Tadpole @@ -5711,7 +5711,7 @@ Derived from [Entity](#Entity) [Movable](#Movable) [PowerupCapable](#PowerupCapa Type | Name | Description ---- | ---- | ----------- -bool | [show_text](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=show_text) | if set to true, he will say 'i've been hunting this fiend a long time!' when on screen +bool | [show_text](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=show_text) | if set to true, he will say "I've been hunting this fiend a long time!" when on screen bool | [special_message_shown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=special_message_shown) | one way door message has been shown ### Vlad @@ -5951,7 +5951,7 @@ Derived from [Entity](#Entity) [Movable](#Movable) [Purchasable](#Purchasable) Type | Name | Description ---- | ---- | ----------- -float | [get_arrow_special_offset()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_arrow_special_offset) | When lain on the ground +float | [get_arrow_special_offset()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_arrow_special_offset) | When lying on the ground ### Bullet @@ -6926,7 +6926,7 @@ bool | [can_jump()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=can bool | [is_on_fire()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_on_fire) | bool | [is_powerup_capable()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_powerup_capable) | bool | [damage(Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=damage) | Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer -vector<int> | [get_all_behaviors()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_all_behaviors) | Get all avaible behavior ids +vector<int> | [get_all_behaviors()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_all_behaviors) | Get all available behavior ids bool | [set_behavior(int behavior_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_behavior) | Set behavior, this is more than just state as it's an active function, for example climbing ladder is a behavior and it doesn't actually need ladder/rope entity
Returns false if entity doesn't have this behavior id int | [get_behavior()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_behavior) | Get the current behavior id nil | [set_gravity(float gravity)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_gravity) | Force the gravity for this entity. Will override anything set by special states like swimming too, unless you reset it. Default 1.0 diff --git a/src/game_api/entities_items.hpp b/src/game_api/entities_items.hpp index 03cdce022..cc1fe74bf 100644 --- a/src/game_api/entities_items.hpp +++ b/src/game_api/entities_items.hpp @@ -861,7 +861,7 @@ class PrizeDispenser : public Movable class Bow : public Purchasable { public: - /// When lain on the ground + /// When lying on the ground virtual float get_arrow_special_offset() = 0; }; diff --git a/src/game_api/entities_monsters.hpp b/src/game_api/entities_monsters.hpp index 19aadb62f..33064b43a 100644 --- a/src/game_api/entities_monsters.hpp +++ b/src/game_api/entities_monsters.hpp @@ -25,7 +25,7 @@ class Monster : public PowerupCapable virtual bool update_target(Entity* ent, float&) = 0; // 100, float from the function above, also works as an output? }; -// RoomOwner and NPC may have common subclass for the first two virtuals, but they later dirvarge, wepon type is the same spot, but they probably just made one first then copied over the virtuals +// RoomOwner and NPC may have common subclass for the first two virtuals, but they later diverge, weapon type is the same spot, but they probably just made one first then copied over the virtuals class RoomOwner : public Monster { public: @@ -89,7 +89,7 @@ class NPC : public Monster virtual ENT_TYPE weapon_type() = 0; /// For weapons, checks if the entity should hit the trigger or not virtual bool should_attack(std::tuple target) = 0; - virtual void on_criminal_act_committed2(void*) = 0; // calls the on_criminal_act_committed except for bodyguard which calls the should_attack_on_sight and turns off any speechbubble + virtual void on_criminal_act_committed2(void*) = 0; // calls the on_criminal_act_committed except for bodyguard which calls the should_attack_on_sight and turns off any speech-bubble }; class WalkingMonster : public Monster @@ -378,7 +378,7 @@ class Lavamander : public Monster uint16_t jump_pause_timer; // jump pause when cool; runs continuously when hot uint8_t lava_detection_timer; bool is_hot; - /// 0 - didnt_saw_player, 1 - saw_player, 2 - spited_lava; probably used so he won't spit imminently after seeing the player + /// 0 - didn't saw player, 1 - saw player, 2 - spited lava; probably used so he won't spit imminently after seeing the player uint8_t player_detect_state; uint8_t padding2; }; diff --git a/src/game_api/entity.hpp b/src/game_api/entity.hpp index 3acbc823c..ab21a4815 100644 --- a/src/game_api/entity.hpp +++ b/src/game_api/entity.hpp @@ -283,7 +283,7 @@ class Entity /// Returns true if entity is in water/lava virtual bool is_in_liquid() = 0; // 12, drill always returns false virtual bool check_type_properties_flags_19() = 0; // 13, checks (properties_flags >> 0x12) & 1; for hermitcrab checks if he's invisible; can't get it to trigger - virtual uint8_t get_type_field_60() = 0; // 14, the value is compared to entity state and used in some bahavior function + virtual uint8_t get_type_field_60() = 0; // 14, the value is compared to entity state and used in some behavior function virtual void set_invisible(bool value) = 0; // 15 virtual void flip(bool left) = 0; // 16 virtual void set_draw_depth(uint8_t draw_depth, uint8_t b3f) = 0; // 17 @@ -293,7 +293,7 @@ class Entity virtual void remove_item(Entity* entity, bool autokill_check) = 0; // 21, if autokill_check is true, it will check if the entity has the "kill if overlay lost" flag and kill it if it's set virtual Entity* get_held_entity() = 0; // 22 virtual void v23(Entity* logical_trigger, Entity* who_triggered_it) = 0; // 23, spawns LASERTRAP_SHOT from LASERTRAP, also some trigger entities use this, seam to be called right after "on_collision2", triggers use self as the first parameter. Called when there is entity overlapping trigger entity, even if they don't move - /// Triggers weapons and other held items like teleportter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) + /// Triggers weapons and other held items like teleporter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) virtual bool trigger_action(Entity* user) = 0; // 24, also used for throwables, disabling this for bomb make it always spawn an the ground, but you can still pick it up and throw it /// Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) virtual void activate(Entity* activator) = 0; // 25 diff --git a/src/game_api/movable.hpp b/src/game_api/movable.hpp index 9fced6fd6..312420b81 100644 --- a/src/game_api/movable.hpp +++ b/src/game_api/movable.hpp @@ -216,7 +216,7 @@ class Movable : public Entity virtual void initialize() = 0; // 75, e.g. cobra: set random spit_timer; bat: set random stand_counter; emerald: set price virtual void check_is_falling() = 0; // 76, sets more_flags.falling by comparing velocityy to 0, sets i120a to FF, clears owner_uid, can call remove_rider on mounts, for player updates the extra y_pos, for bosses clears lock input timer virtual void v77() = 0; // 77 - virtual void process_input() = 0; // 78, more like: handle_movment + virtual void process_input() = 0; // 78, more like: handle_movement virtual void post_collision_damage_related() = 0; // 79, used for enemies attacks as well? 3 versions for: eggplant minister, players and the rest virtual void on_picked_up() = 0; // 80, plays pickup sound depending on the entity mask/type etc. set stun for pets and mounts etc. virtual void on_release() = 0; // 81, only for hired hands and lava pots From 6b7d54fb0e4025b14a59a7ab9ac17b57952368df Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 12 Sep 2024 14:40:16 +0200 Subject: [PATCH 06/21] update and fix entity casting, also rename variables in `Animation` --- docs/entities-hierarchy.md | 26 +++++++++---------- src/game_api/entities_items.hpp | 2 +- src/game_api/entity_structs.hpp | 6 ++--- src/game_api/script/lua_console.cpp | 7 ++--- .../script/usertypes/entities_items_lua.cpp | 8 ++++++ .../script/usertypes/entity_casting.py | 2 +- .../script/usertypes/entity_casting_lua.cpp | 4 +-- src/game_api/script/usertypes/entity_lua.cpp | 4 +-- src/info_dump/main.cpp | 2 +- src/injected/ui.cpp | 10 +++---- 10 files changed, 40 insertions(+), 31 deletions(-) diff --git a/docs/entities-hierarchy.md b/docs/entities-hierarchy.md index a7f22ceef..ce02eea6e 100644 --- a/docs/entities-hierarchy.md +++ b/docs/entities-hierarchy.md @@ -541,22 +541,22 @@ The list below shows the type hierarchy for each entity in the game. This makes - 560 ITEM_POWERUP_ANKH = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Powerup](https://spelunky-fyi.github.io/overlunky/#Powerup) > [AnkhPowerup](https://spelunky-fyi.github.io/overlunky/#AnkhPowerup) - 561 ITEM_POWERUP_TABLETOFDESTINY = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Powerup](https://spelunky-fyi.github.io/overlunky/#Powerup) - 562 ITEM_POWERUP_SKELETON_KEY = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Powerup](https://spelunky-fyi.github.io/overlunky/#Powerup) -- 564 ITEM_CAPE = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [Cape](https://spelunky-fyi.github.io/overlunky/#Cape) > [YellowCape](https://spelunky-fyi.github.io/overlunky/#YellowCape) -- 565 ITEM_VLADS_CAPE = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [Cape](https://spelunky-fyi.github.io/overlunky/#Cape) > [VladsCape](https://spelunky-fyi.github.io/overlunky/#VladsCape) -- 566 ITEM_PURCHASABLE_CAPE = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [DummyPurchasableEntity](https://spelunky-fyi.github.io/overlunky/#DummyPurchasableEntity) -- 567 ITEM_JETPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [Jetpack](https://spelunky-fyi.github.io/overlunky/#Jetpack) -- 568 ITEM_JETPACK_MECH = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [Jetpack](https://spelunky-fyi.github.io/overlunky/#Jetpack) +- 564 ITEM_CAPE = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Powerup](https://spelunky-fyi.github.io/overlunky/#Powerup) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [Cape](https://spelunky-fyi.github.io/overlunky/#Cape) > [YellowCape](https://spelunky-fyi.github.io/overlunky/#YellowCape) +- 565 ITEM_VLADS_CAPE = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Powerup](https://spelunky-fyi.github.io/overlunky/#Powerup) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [Cape](https://spelunky-fyi.github.io/overlunky/#Cape) > [VladsCape](https://spelunky-fyi.github.io/overlunky/#VladsCape) +- 566 ITEM_PURCHASABLE_CAPE = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) +- 567 ITEM_JETPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Powerup](https://spelunky-fyi.github.io/overlunky/#Powerup) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [Jetpack](https://spelunky-fyi.github.io/overlunky/#Jetpack) +- 568 ITEM_JETPACK_MECH = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Powerup](https://spelunky-fyi.github.io/overlunky/#Powerup) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [Jetpack](https://spelunky-fyi.github.io/overlunky/#Jetpack) - 569 ITEM_PURCHASABLE_JETPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [DummyPurchasableEntity](https://spelunky-fyi.github.io/overlunky/#DummyPurchasableEntity) -- 570 ITEM_TELEPORTER_BACKPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [TeleporterBackpack](https://spelunky-fyi.github.io/overlunky/#TeleporterBackpack) +- 570 ITEM_TELEPORTER_BACKPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Powerup](https://spelunky-fyi.github.io/overlunky/#Powerup) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [TeleporterBackpack](https://spelunky-fyi.github.io/overlunky/#TeleporterBackpack) - 571 ITEM_PURCHASABLE_TELEPORTER_BACKPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [DummyPurchasableEntity](https://spelunky-fyi.github.io/overlunky/#DummyPurchasableEntity) -- 572 ITEM_HOVERPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [Hoverpack](https://spelunky-fyi.github.io/overlunky/#Hoverpack) +- 572 ITEM_HOVERPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Powerup](https://spelunky-fyi.github.io/overlunky/#Powerup) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) > [Hoverpack](https://spelunky-fyi.github.io/overlunky/#Hoverpack) - 573 ITEM_PURCHASABLE_HOVERPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [DummyPurchasableEntity](https://spelunky-fyi.github.io/overlunky/#DummyPurchasableEntity) -- 574 ITEM_POWERPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) +- 574 ITEM_POWERPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Powerup](https://spelunky-fyi.github.io/overlunky/#Powerup) > [Backpack](https://spelunky-fyi.github.io/overlunky/#Backpack) - 575 ITEM_PURCHASABLE_POWERPACK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [DummyPurchasableEntity](https://spelunky-fyi.github.io/overlunky/#DummyPurchasableEntity) - 576 ITEM_WEBGUN = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Gun](https://spelunky-fyi.github.io/overlunky/#Gun) - 577 ITEM_SHOTGUN = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Gun](https://spelunky-fyi.github.io/overlunky/#Gun) - 578 ITEM_FREEZERAY = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Gun](https://spelunky-fyi.github.io/overlunky/#Gun) -- 579 ITEM_CROSSBOW = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Bow](https://spelunky-fyi.github.io/overlunky/#Bow) +- 579 ITEM_CROSSBOW = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Bow](https://spelunky-fyi.github.io/overlunky/#Bow) - 580 ITEM_CAMERA = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Gun](https://spelunky-fyi.github.io/overlunky/#Gun) - 581 ITEM_TELEPORTER = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Teleporter](https://spelunky-fyi.github.io/overlunky/#Teleporter) - 582 ITEM_MATTOCK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Mattock](https://spelunky-fyi.github.io/overlunky/#Mattock) @@ -565,9 +565,9 @@ The list below shows the type hierarchy for each entity in the game. This makes - 585 ITEM_EXCALIBUR = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Excalibur](https://spelunky-fyi.github.io/overlunky/#Excalibur) - 586 ITEM_BROKENEXCALIBUR = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) - 587 ITEM_PLASMACANNON = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Gun](https://spelunky-fyi.github.io/overlunky/#Gun) -- 588 ITEM_SCEPTER = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Gun](https://spelunky-fyi.github.io/overlunky/#Gun) +- 588 ITEM_SCEPTER = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) - [Scepter](https://spelunky-fyi.github.io/overlunky/#Scepter) - 589 ITEM_CLONEGUN = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Gun](https://spelunky-fyi.github.io/overlunky/#Gun) -- 590 ITEM_HOUYIBOW = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Bow](https://spelunky-fyi.github.io/overlunky/#Bow) +- 590 ITEM_HOUYIBOW = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Bow](https://spelunky-fyi.github.io/overlunky/#Bow) - 591 ITEM_WOODEN_SHIELD = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Shield](https://spelunky-fyi.github.io/overlunky/#Shield) - 592 ITEM_METAL_SHIELD = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [Purchasable](https://spelunky-fyi.github.io/overlunky/#Purchasable) > [Shield](https://spelunky-fyi.github.io/overlunky/#Shield) - 596 ACTIVEFLOOR_EGGSHIPPLATFORM = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) @@ -597,7 +597,7 @@ The list below shows the type hierarchy for each entity in the game. This makes - 620 ACTIVEFLOOR_TIAMAT_PLATFORM = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) - 621 ACTIVEFLOOR_TIAMAT_SHOULDERPLATFORM = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) - 622 ACTIVEFLOOR_BUBBLE_PLATFORM = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) -- 623 ACTIVEFLOOR_CRUSHING_ELEVATOR = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) +- 623 ACTIVEFLOOR_CRUSHING_ELEVATOR = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [CrushElevator](https://spelunky-fyi.github.io/overlunky/#CrushElevator) - 624 ACTIVEFLOOR_SHIELD = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) - 625 ACTIVEFLOOR_REGENERATINGBLOCK = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) > [RegenBlock](https://spelunky-fyi.github.io/overlunky/#RegenBlock) - 628 FX_EGGSHIP_SHELL = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [Movable](https://spelunky-fyi.github.io/overlunky/#Movable) @@ -772,7 +772,7 @@ The list below shows the type hierarchy for each entity in the game. This makes - 801 BG_BASECAMP_DININGTABLE_DISHES = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) - 802 BG_BASECAMP_SHORTCUTSTATIONBANNER = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) - 803 BG_SHOP = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) -- 804 BG_SHOP_ENTRANCEDOOR = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [BGShopEntrence](https://spelunky-fyi.github.io/overlunky/#BGShopEntrence) +- 804 BG_SHOP_ENTRANCEDOOR = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) > [BGShopEntrance](https://spelunky-fyi.github.io/overlunky/#BGShopEntrance) - 805 BG_SHOP_BACKDOOR = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) - 806 BG_SHOPWANTEDPOSTER = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) - 807 BG_SHOPWANTEDPORTRAIT = [Entity](https://spelunky-fyi.github.io/overlunky/#Entity) diff --git a/src/game_api/entities_items.hpp b/src/game_api/entities_items.hpp index cc1fe74bf..1604008f7 100644 --- a/src/game_api/entities_items.hpp +++ b/src/game_api/entities_items.hpp @@ -117,7 +117,7 @@ class Mattock : public Purchasable }; class Gun : public Purchasable -{ // BIG NOTE: scepter is not a Purchasable, but that's the only Gun that isn't so i didn't bother to make new type for it +{ public: uint8_t cooldown; /// used only for webgun diff --git a/src/game_api/entity_structs.hpp b/src/game_api/entity_structs.hpp index 7f138b79e..1495ab502 100644 --- a/src/game_api/entity_structs.hpp +++ b/src/game_api/entity_structs.hpp @@ -27,10 +27,10 @@ enum class SHAPE : uint8_t struct Animation { - int32_t texture; - int32_t count; + int32_t first_tile; + int32_t count; // num_tiles int32_t interval; - uint8_t key; + uint8_t id; REPEAT_TYPE repeat; }; diff --git a/src/game_api/script/lua_console.cpp b/src/game_api/script/lua_console.cpp index cad431057..107553d6e 100644 --- a/src/game_api/script/lua_console.cpp +++ b/src/game_api/script/lua_console.cpp @@ -61,7 +61,7 @@ LuaConsole::LuaConsole(SoundManager* soundmanager) {"BGBackLayerDoor", "as_entity"}, {"BGSurfaceLayer", "as_bgrelativeelement"}, {"BGEggshipRoom", "as_entity"}, - {"BGShopEntrence", "as_entity"}, + {"BGShopEntrance", "as_entity"}, {"BGMovingStar", "as_bgsurfacestar"}, {"BGRelativeElement", "as_entity"}, {"BGShootingStar", "as_bgrelativeelement"}, @@ -165,7 +165,7 @@ LuaConsole::LuaConsole(SoundManager* soundmanager) {"AcidBubble", "as_movable"}, {"Claw", "as_movable"}, {"StretchChain", "as_movable"}, - {"Bow", "as_movable"}, + {"Bow", "as_purchasable"}, {"CursedPot", "as_movable"}, {"PrizeDispenser", "as_movable"}, {"EggSac", "as_movable"}, @@ -213,7 +213,7 @@ LuaConsole::LuaConsole(SoundManager* soundmanager) {"PlayerGhost", "as_lightemitter"}, {"GhostBreath", "as_projectile"}, {"Pot", "as_purchasable"}, - {"Backpack", "as_movable"}, + {"Backpack", "as_powerup"}, {"AnkhPowerup", "as_powerup"}, {"Powerup", "as_movable"}, {"KapalaPowerup", "as_powerup"}, @@ -222,6 +222,7 @@ LuaConsole::LuaConsole(SoundManager* soundmanager) {"PunishBall", "as_movable"}, {"DummyPurchasableEntity", "as_purchasable"}, {"Rubble", "as_movable"}, + {"Scepter", "as_movable"}, {"ScepterShot", "as_lightemitter"}, {"SpecialShot", "as_lightemitter"}, {"SkullDropTrap", "as_movable"}, diff --git a/src/game_api/script/usertypes/entities_items_lua.cpp b/src/game_api/script/usertypes/entities_items_lua.cpp index 73cd3b747..979355ac5 100644 --- a/src/game_api/script/usertypes/entities_items_lua.cpp +++ b/src/game_api/script/usertypes/entities_items_lua.cpp @@ -122,6 +122,7 @@ void register_usertypes(sol::state& lua) lua["Entity"]["as_shield"] = &Entity::as; lua["Entity"]["as_powerup"] = &Entity::as; lua["Entity"]["as_prizedispenser"] = &Entity::as; + lua["Entity"]["as_scepter"] = &Entity::as; lua.new_usertype( "Bomb", @@ -1027,5 +1028,12 @@ void register_usertypes(sol::state& lua) &Web::decay_rate, sol::base_classes, sol::bases()); + + lua.new_usertype( + "Scepter", + "cooldown", + &Scepter::cooldown, + sol::base_classes, + sol::bases()); } } // namespace NEntitiesItems diff --git a/src/game_api/script/usertypes/entity_casting.py b/src/game_api/script/usertypes/entity_casting.py index c0a97a9b4..7c8679f71 100644 --- a/src/game_api/script/usertypes/entity_casting.py +++ b/src/game_api/script/usertypes/entity_casting.py @@ -30,7 +30,7 @@ # Download Spelunky2.json from the x64dbg github repo #url = "https://gitcdn.link/repo/spelunky-fyi/Spelunky2X64DbgPlugin/master/resources/Spelunky2.json" -url = "https://raw.githubusercontent.com/spelunky-fyi/Spelunky2X64DbgPlugin/master/resources/Spelunky2.json" +url = "https://raw.githubusercontent.com/spelunky-fyi/Spelunky2X64DbgPlugin/master/resources/Spelunky2Entities.json" response = urllib.request.urlopen(url) spelunky2json = response.read().decode('utf-8') j = json.loads(re.sub("//.*", "", spelunky2json, flags=re.MULTILINE)) diff --git a/src/game_api/script/usertypes/entity_casting_lua.cpp b/src/game_api/script/usertypes/entity_casting_lua.cpp index f725f1685..2c88b34ce 100644 --- a/src/game_api/script/usertypes/entity_casting_lua.cpp +++ b/src/game_api/script/usertypes/entity_casting_lua.cpp @@ -557,7 +557,7 @@ void register_usertypes(sol::state& lua) lua["TYPE_MAP"][562] = lua["Entity"]["as_powerup"]; // ITEM_POWERUP_SKELETON_KEY lua["TYPE_MAP"][564] = lua["Entity"]["as_yellowcape"]; // ITEM_CAPE lua["TYPE_MAP"][565] = lua["Entity"]["as_vladscape"]; // ITEM_VLADS_CAPE - lua["TYPE_MAP"][566] = lua["Entity"]["as_dummypurchasableentity"]; // ITEM_PURCHASABLE_CAPE + lua["TYPE_MAP"][566] = lua["Entity"]["as_purchasable"]; // ITEM_PURCHASABLE_CAPE lua["TYPE_MAP"][567] = lua["Entity"]["as_jetpack"]; // ITEM_JETPACK lua["TYPE_MAP"][568] = lua["Entity"]["as_jetpack"]; // ITEM_JETPACK_MECH lua["TYPE_MAP"][569] = lua["Entity"]["as_dummypurchasableentity"]; // ITEM_PURCHASABLE_JETPACK @@ -579,7 +579,7 @@ void register_usertypes(sol::state& lua) lua["TYPE_MAP"][585] = lua["Entity"]["as_excalibur"]; // ITEM_EXCALIBUR lua["TYPE_MAP"][586] = lua["Entity"]["as_movable"]; // ITEM_BROKENEXCALIBUR lua["TYPE_MAP"][587] = lua["Entity"]["as_gun"]; // ITEM_PLASMACANNON - lua["TYPE_MAP"][588] = lua["Entity"]["as_gun"]; // ITEM_SCEPTER + lua["TYPE_MAP"][588] = lua["Entity"]["as_scepter"]; // ITEM_SCEPTER lua["TYPE_MAP"][589] = lua["Entity"]["as_gun"]; // ITEM_CLONEGUN lua["TYPE_MAP"][590] = lua["Entity"]["as_bow"]; // ITEM_HOUYIBOW lua["TYPE_MAP"][591] = lua["Entity"]["as_shield"]; // ITEM_WOODEN_SHIELD diff --git a/src/game_api/script/usertypes/entity_lua.cpp b/src/game_api/script/usertypes/entity_lua.cpp index 2e00a173c..e82f75b94 100644 --- a/src/game_api/script/usertypes/entity_lua.cpp +++ b/src/game_api/script/usertypes/entity_lua.cpp @@ -32,9 +32,9 @@ void register_usertypes(sol::state& lua) lua.new_usertype( "Animation", "id", - &Animation::key, + &Animation::id, "first_tile", - &Animation::texture, + &Animation::first_tile, "num_tiles", &Animation::count, "interval", diff --git a/src/info_dump/main.cpp b/src/info_dump/main.cpp index b75ebfd7c..0c13f84c0 100644 --- a/src/info_dump/main.cpp +++ b/src/info_dump/main.cpp @@ -1026,7 +1026,7 @@ void get_vtables() } } -FLOAT_JSON_DEFINE_TYPE_NON_INTRUSIVE(Animation, texture, count, interval, key, repeat); +FLOAT_JSON_DEFINE_TYPE_NON_INTRUSIVE(Animation, first_tile, count, interval, id, repeat); FLOAT_JSON_DEFINE_TYPE_NON_INTRUSIVE(Rect, offsetx, offsety, hitboxx, hitboxy); void to_json(float_json& j, const EntityDB& ent) { diff --git a/src/injected/ui.cpp b/src/injected/ui.cpp index 7d97af08d..95a3bdffc 100644 --- a/src/injected/ui.cpp +++ b/src/injected/ui.cpp @@ -8144,8 +8144,8 @@ void render_hotbar_textures() auto anim = type->animations.begin()->second; if (type->animations.contains(0)) anim = type->animations[0]; - tx = anim.texture % (def.sub_image_width / def.tile_width); - ty = (uint32_t)floor(anim.texture / (def.sub_image_height / def.tile_height)); + tx = anim.first_tile % (def.sub_image_width / def.tile_width); + ty = (uint32_t)floor(anim.first_tile / (def.sub_image_height / def.tile_height)); } float uv_left = (texture->tile_width_fraction * tx) + texture->offset_x_weird_math; float uv_right = uv_left + texture->tile_width_fraction - texture->one_over_width; @@ -8286,8 +8286,8 @@ void render_texture_viewer() std::map, int> overlap; for (const auto& [id, anim] : ent->type->animations) { - uint32_t x = def.sub_image_offset_x + def.tile_width * (anim.texture % (def.sub_image_width / def.tile_width)); - uint32_t y = def.sub_image_offset_y + def.tile_height * (uint32_t)floor(anim.texture / (def.sub_image_height / def.tile_height)); + uint32_t x = def.sub_image_offset_x + def.tile_width * (anim.first_tile % (def.sub_image_width / def.tile_width)); + uint32_t y = def.sub_image_offset_y + def.tile_height * (uint32_t)floor(anim.first_tile / (def.sub_image_height / def.tile_height)); bool rev = anim.count < 0; auto key = std::make_tuple(x, y, rev); float tx = 0; @@ -8310,7 +8310,7 @@ void render_texture_viewer() dl->AddRect({ax - 3, ay + 3}, {bx + 3, by - 3}, border, 0, 0, thick); else dl->AddRect({ax + 3, ay + 3}, {bx - 3, by - 3}, border, 0, 0, thick); - dl->AddText({ax + tx, ay + f * def.tile_height - ImGui::GetTextLineHeight() - 4}, 0xffffffff, fmt::format("{}", anim.key).c_str()); + dl->AddText({ax + tx, ay + f * def.tile_height - ImGui::GetTextLineHeight() - 4}, 0xffffffff, fmt::format("{}", anim.id).c_str()); overlap[key]++; } } From c417296d3ae2f637893180ae417a3ab5cf9eedce Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 12 Sep 2024 15:28:43 +0200 Subject: [PATCH 07/21] update vtable names for `vtable_sizes.csv`, update full doscs --- docs/game_data/entities.json | 11730 ++++++++++---------- docs/game_data/entities_texture_only.json | 11730 ++++++++++---------- docs/game_data/lua_enums.txt | 139 +- docs/game_data/spel2.lua | 144 +- docs/game_data/vtable_sizes.csv | 8 +- docs/src/includes/_casting.md | 1 + docs/src/includes/_types.md | 9 + src/info_dump/main.cpp | 8 +- 8 files changed, 11921 insertions(+), 11848 deletions(-) diff --git a/docs/game_data/entities.json b/docs/game_data/entities.json index 1709d9cf7..1b0f12776 100644 --- a/docs/game_data/entities.json +++ b/docs/game_data/entities.json @@ -3028,318 +3028,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -3372,318 +3372,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -3716,318 +3716,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -4060,318 +4060,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -4404,318 +4404,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -4748,318 +4748,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -5092,318 +5092,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -5436,318 +5436,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -5780,318 +5780,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -6124,318 +6124,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -6468,318 +6468,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -6812,318 +6812,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -7156,318 +7156,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -7500,318 +7500,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -7844,318 +7844,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -8188,318 +8188,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -8532,318 +8532,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -8876,318 +8876,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -9220,318 +9220,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -9564,318 +9564,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -9908,318 +9908,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -10252,318 +10252,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.15, @@ -16392,10 +16392,10 @@ "animations": { "0": { "count": 12, + "first_tile": 48, + "id": 0, "interval": 4, - "key": 0, - "repeat": 1, - "texture": 48 + "repeat": 1 } }, "attachOffsetX": 0.0, @@ -16652,10 +16652,10 @@ "animations": { "22": { "count": 3, + "first_tile": 5, + "id": 22, "interval": 4, - "key": 22, - "repeat": 1, - "texture": 5 + "repeat": 1 } }, "attachOffsetX": 0.0, @@ -16884,10 +16884,10 @@ "animations": { "0": { "count": 16, + "first_tile": 0, + "id": 0, "interval": 2, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -17032,10 +17032,10 @@ "animations": { "3": { "count": 5, + "first_tile": 10, + "id": 3, "interval": 8, - "key": 3, - "repeat": 0, - "texture": 10 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -17180,24 +17180,24 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "41": { "count": 3, + "first_tile": 0, + "id": 41, "interval": 5, - "key": 41, - "repeat": 2, - "texture": 0 + "repeat": 2 }, "5": { "count": 3, + "first_tile": 0, + "id": 5, "interval": 8, - "key": 5, - "repeat": 2, - "texture": 0 + "repeat": 2 } }, "attachOffsetX": 0.0, @@ -17286,10 +17286,10 @@ "animations": { "0": { "count": 3, + "first_tile": 24, + "id": 0, "interval": 2, - "key": 0, - "repeat": 1, - "texture": 24 + "repeat": 1 } }, "attachOffsetX": -0.05, @@ -17322,31 +17322,31 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 4, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 4 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 25, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 25 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 1, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 1 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -17547,10 +17547,10 @@ "animations": { "0": { "count": 8, + "first_tile": 0, + "id": 0, "interval": 4, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -17611,17 +17611,17 @@ "animations": { "0": { "count": 1, + "first_tile": 133, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 133 + "repeat": 0 }, "32": { "count": 5, + "first_tile": 134, + "id": 32, "interval": 4, - "key": 32, - "repeat": 1, - "texture": 134 + "repeat": 1 } }, "attachOffsetX": 0.0, @@ -17990,10 +17990,10 @@ "animations": { "0": { "count": 16, + "first_tile": 0, + "id": 0, "interval": 2, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -18026,10 +18026,10 @@ "animations": { "0": { "count": 6, + "first_tile": 32, + "id": 0, "interval": 4, - "key": 0, - "repeat": 1, - "texture": 32 + "repeat": 1 } }, "attachOffsetX": 0.5, @@ -18062,17 +18062,17 @@ "animations": { "0": { "count": 1, + "first_tile": 38, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 38 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 39, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 39 + "repeat": 0 } }, "attachOffsetX": 0.4, @@ -18469,10 +18469,10 @@ "animations": { "0": { "count": 16, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -18729,10 +18729,10 @@ "animations": { "0": { "count": 5, + "first_tile": 0, + "id": 0, "interval": 2, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -18765,10 +18765,10 @@ "animations": { "0": { "count": 7, + "first_tile": 185, + "id": 0, "interval": 6, - "key": 0, - "repeat": 1, - "texture": 185 + "repeat": 1 } }, "attachOffsetX": 0.3, @@ -18857,10 +18857,10 @@ "animations": { "0": { "count": 7, + "first_tile": 9, + "id": 0, "interval": 3, - "key": 0, - "repeat": 1, - "texture": 9 + "repeat": 1 } }, "attachOffsetX": 0.0, @@ -18893,10 +18893,10 @@ "animations": { "0": { "count": 7, + "first_tile": 9, + "id": 0, "interval": 2, - "key": 0, - "repeat": 1, - "texture": 9 + "repeat": 1 } }, "attachOffsetX": 0.0, @@ -19181,45 +19181,45 @@ "animations": { "0": { "count": 1, + "first_tile": 4, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 4 + "repeat": 0 }, "12": { "count": 3, + "first_tile": 13, + "id": 12, "interval": 4, - "key": 12, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 12, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "19": { "count": 3, + "first_tile": 5, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 5 + "repeat": 0 }, "45": { "count": -3, + "first_tile": 7, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 7 + "repeat": 0 }, "46": { "count": -3, + "first_tile": 15, + "id": 46, "interval": 4, - "key": 46, - "repeat": 0, - "texture": 15 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -19588,10 +19588,10 @@ "animations": { "0": { "count": 5, + "first_tile": 59, + "id": 0, "interval": 4, - "key": 0, - "repeat": 0, - "texture": 59 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -19680,10 +19680,10 @@ "animations": { "0": { "count": 4, + "first_tile": 24, + "id": 0, "interval": 6, - "key": 0, - "repeat": 1, - "texture": 24 + "repeat": 1 } }, "attachOffsetX": 0.0, @@ -20220,59 +20220,59 @@ "animations": { "0": { "count": 1, + "first_tile": 116, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 116 + "repeat": 0 }, "10": { "count": 1, + "first_tile": 121, + "id": 10, "interval": 1, - "key": 10, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 40, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 40 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 117, + "id": 2, "interval": 1, - "key": 2, - "repeat": 0, - "texture": 117 + "repeat": 0 }, "22": { "count": 1, + "first_tile": 124, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "32": { "count": 6, + "first_tile": 118, + "id": 32, "interval": 6, - "key": 32, - "repeat": 1, - "texture": 118 + "repeat": 1 }, "5": { "count": 3, + "first_tile": 125, + "id": 5, "interval": 3, - "key": 5, - "repeat": 1, - "texture": 125 + "repeat": 1 }, "6": { "count": 3, + "first_tile": 125, + "id": 6, "interval": 6, - "key": 6, - "repeat": 1, - "texture": 125 + "repeat": 1 } }, "attachOffsetX": -0.25, @@ -20725,10 +20725,10 @@ "animations": { "41": { "count": 8, + "first_tile": 48, + "id": 41, "interval": 4, - "key": 41, - "repeat": 0, - "texture": 48 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -20873,10 +20873,10 @@ "animations": { "22": { "count": 6, + "first_tile": 229, + "id": 22, "interval": 3, - "key": 22, - "repeat": 1, - "texture": 229 + "repeat": 1 } }, "attachOffsetX": 0.28, @@ -20965,24 +20965,24 @@ "animations": { "0": { "count": 1, + "first_tile": 167, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 167 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 168, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 168 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 169, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 169 + "repeat": 1 } }, "attachOffsetX": 0.0, @@ -21323,10 +21323,10 @@ "animations": { "41": { "count": 4, + "first_tile": 12, + "id": 41, "interval": 2, - "key": 41, - "repeat": 2, - "texture": 12 + "repeat": 2 } }, "attachOffsetX": 0.4, @@ -21471,31 +21471,31 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "27": { "count": 2, + "first_tile": 1, + "id": 27, "interval": 2, - "key": 27, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "28": { "count": -2, + "first_tile": 2, + "id": 28, "interval": 2, - "key": 28, - "repeat": 0, - "texture": 2 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 3, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 3 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -21528,31 +21528,31 @@ "animations": { "0": { "count": 1, + "first_tile": 102, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 102 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 103, + "id": 2, "interval": 6, - "key": 2, - "repeat": 0, - "texture": 103 + "repeat": 0 }, "45": { "count": 4, + "first_tile": 104, + "id": 45, "interval": 6, - "key": 45, - "repeat": 0, - "texture": 104 + "repeat": 0 }, "46": { "count": 4, + "first_tile": 108, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 108 + "repeat": 0 } }, "attachOffsetX": 0.5, @@ -21613,17 +21613,17 @@ "animations": { "0": { "count": 1, + "first_tile": 139, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 139, + "id": 2, "interval": 4, - "key": 2, - "repeat": 0, - "texture": 139 + "repeat": 0 } }, "attachOffsetX": 0.35, @@ -21656,17 +21656,17 @@ "animations": { "0": { "count": 1, + "first_tile": 155, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 155 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 155, + "id": 2, "interval": 4, - "key": 2, - "repeat": 0, - "texture": 155 + "repeat": 0 } }, "attachOffsetX": 0.4, @@ -21699,17 +21699,17 @@ "animations": { "0": { "count": 1, + "first_tile": 220, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 220 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 215, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 215 + "repeat": 1 } }, "attachOffsetX": 0.35, @@ -21910,24 +21910,24 @@ "animations": { "0": { "count": 1, + "first_tile": 149, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 149 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 148, + "id": 2, "interval": 1, - "key": 2, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "5": { "count": 2, + "first_tile": 150, + "id": 5, "interval": 4, - "key": 5, - "repeat": 1, - "texture": 150 + "repeat": 1 } }, "attachOffsetX": -0.25, @@ -22688,17 +22688,17 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 128, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 128 + "repeat": 0 } }, "attachOffsetX": 0.35, @@ -22899,10 +22899,10 @@ "animations": { "41": { "count": 8, + "first_tile": 128, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 128 + "repeat": 1 } }, "attachOffsetX": 0.4, @@ -24167,38 +24167,38 @@ "animations": { "12": { "count": 1, + "first_tile": 186, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 186 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 172, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 172 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 160, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "45": { "count": 4, + "first_tile": 164, + "id": 45, "interval": 2, - "key": 45, - "repeat": 0, - "texture": 164 + "repeat": 0 }, "46": { "count": 2, + "first_tile": 168, + "id": 46, "interval": 4, - "key": 46, - "repeat": 1, - "texture": 168 + "repeat": 1 } }, "attachOffsetX": 0.4, @@ -24343,17 +24343,17 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 7, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 7 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -25730,17 +25730,17 @@ "animations": { "0": { "count": 1, + "first_tile": 199, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 199 + "repeat": 0 }, "19": { "count": 1, + "first_tile": 200, + "id": 19, "interval": 1, - "key": 19, - "repeat": 0, - "texture": 200 + "repeat": 0 } }, "attachOffsetX": 0.35, @@ -26305,45 +26305,45 @@ "animations": { "0": { "count": 1, + "first_tile": 248, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 248 + "repeat": 0 }, "10": { "count": 1, + "first_tile": 249, + "id": 10, "interval": 10, - "key": 10, - "repeat": 0, - "texture": 249 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 249, + "id": 12, "interval": 30, - "key": 12, - "repeat": 0, - "texture": 249 + "repeat": 0 }, "32": { "count": 2, + "first_tile": 250, + "id": 32, "interval": 16, - "key": 32, - "repeat": 1, - "texture": 250 + "repeat": 1 }, "45": { "count": 2, + "first_tile": 252, + "id": 45, "interval": 16, - "key": 45, - "repeat": 1, - "texture": 252 + "repeat": 1 }, "46": { "count": 2, + "first_tile": 254, + "id": 46, "interval": 16, - "key": 46, - "repeat": 1, - "texture": 254 + "repeat": 1 } }, "attachOffsetX": 0.4, @@ -26516,45 +26516,45 @@ "animations": { "0": { "count": 1, + "first_tile": 101, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 101 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 99, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 99 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 100, + "id": 2, "interval": 1, - "key": 2, - "repeat": 0, - "texture": 100 + "repeat": 0 }, "3": { "count": 4, + "first_tile": 103, + "id": 3, "interval": 3, - "key": 3, - "repeat": 0, - "texture": 103 + "repeat": 0 }, "41": { "count": 5, + "first_tile": 102, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 102, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 102 + "repeat": 0 } }, "attachOffsetX": -0.25, @@ -28631,52 +28631,52 @@ "animations": { "0": { "count": 1, + "first_tile": 148, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "11": { "count": 4, + "first_tile": 154, + "id": 11, "interval": 4, - "key": 11, - "repeat": 1, - "texture": 154 + "repeat": 1 }, "2": { "count": 6, + "first_tile": 148, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 148 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 144, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 148, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "5": { "count": 3, + "first_tile": 145, + "id": 5, "interval": 6, - "key": 5, - "repeat": 1, - "texture": 145 + "repeat": 1 }, "6": { "count": 3, + "first_tile": 145, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 145 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -28709,24 +28709,24 @@ "animations": { "13": { "count": 1, + "first_tile": 4, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 4 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 5, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 5 + "repeat": 1 }, "32": { "count": 5, + "first_tile": 5, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 5 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -28759,31 +28759,31 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "19": { "count": 7, + "first_tile": 40, + "id": 19, "interval": 2, - "key": 19, - "repeat": 1, - "texture": 40 + "repeat": 1 }, "2": { "count": 7, + "first_tile": 33, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 53, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 53 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -28816,45 +28816,45 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "19": { "count": 8, + "first_tile": 48, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "3": { "count": 4, + "first_tile": 2, + "id": 3, "interval": 6, - "key": 3, - "repeat": 0, - "texture": 2 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 32, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "45": { "count": 2, + "first_tile": 0, + "id": 45, "interval": 20, - "key": 45, - "repeat": 1, - "texture": 0 + "repeat": 1 }, "46": { "count": 1, + "first_tile": 1, + "id": 46, "interval": 1, - "key": 46, - "repeat": 0, - "texture": 1 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -28887,17 +28887,17 @@ "animations": { "19": { "count": 8, + "first_tile": 56, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 33, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 33 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -29014,24 +29014,24 @@ "animations": { "14": { "count": 1, + "first_tile": 6, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 6 + "repeat": 0 }, "41": { "count": 6, + "first_tile": 22, + "id": 41, "interval": 2, - "key": 41, - "repeat": 1, - "texture": 22 + "repeat": 1 }, "9": { "count": 6, + "first_tile": 6, + "id": 9, "interval": 4, - "key": 9, - "repeat": 0, - "texture": 6 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -29064,31 +29064,31 @@ "animations": { "0": { "count": 1, + "first_tile": 201, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 201 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 223, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 223 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 202, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 202 + "repeat": 1 }, "41": { "count": 6, + "first_tile": 217, + "id": 41, "interval": 2, - "key": 41, - "repeat": 1, - "texture": 217 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -29121,115 +29121,115 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 159, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 159 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 144, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 141, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 141, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 137, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 137 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 138, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 138 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 139, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 140, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 140 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 129, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 149, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 149 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 149, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 149 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 129, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 149, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 149 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 122, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 122, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 122 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -29262,17 +29262,17 @@ "animations": { "0": { "count": 5, + "first_tile": 176, + "id": 0, "interval": 7, - "key": 0, - "repeat": 2, - "texture": 176 + "repeat": 2 }, "32": { "count": 8, + "first_tile": 181, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 181 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -29305,136 +29305,136 @@ "animations": { "0": { "count": 1, + "first_tile": 80, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 107, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 91, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 91, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 105, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 92, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 92 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 93, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 93 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 94, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 94 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 95, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 95 + "repeat": 0 }, "2": { "count": 10, + "first_tile": 81, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 81 + "repeat": 1 }, "20": { "count": 1, + "first_tile": 64, + "id": 20, "interval": 1, - "key": 20, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "22": { "count": 16, + "first_tile": 64, + "id": 22, "interval": 4, - "key": 22, - "repeat": 1, - "texture": 64 + "repeat": 1 }, "28": { "count": 2, + "first_tile": 105, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 96, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "34": { "count": 1, + "first_tile": 106, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "42": { "count": 5, + "first_tile": 165, + "id": 42, "interval": 4, - "key": 42, - "repeat": 1, - "texture": 165 + "repeat": 1 }, "43": { "count": 5, + "first_tile": 160, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "45": { "count": 1, + "first_tile": 104, + "id": 45, "interval": 1, - "key": 45, - "repeat": 0, - "texture": 104 + "repeat": 0 }, "46": { "count": 2, + "first_tile": 104, + "id": 46, "interval": 8, - "key": 46, - "repeat": 1, - "texture": 104 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -29467,73 +29467,73 @@ "animations": { "0": { "count": 6, + "first_tile": 0, + "id": 0, "interval": 8, - "key": 0, - "repeat": 1, - "texture": 0 + "repeat": 1 }, "10": { "count": 4, + "first_tile": 8, + "id": 10, "interval": 4, - "key": 10, - "repeat": 0, - "texture": 8 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 14, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 14 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 16, + "id": 19, "interval": 3, - "key": 19, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "2": { "count": 6, + "first_tile": 24, + "id": 2, "interval": 7, - "key": 2, - "repeat": 1, - "texture": 24 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 13, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "27": { "count": 2, + "first_tile": 8, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 8 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 12, + "id": 3, "interval": 4, - "key": 3, - "repeat": 1, - "texture": 12 + "repeat": 1 }, "45": { "count": 2, + "first_tile": 6, + "id": 45, "interval": 8, - "key": 45, - "repeat": 1, - "texture": 6 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 12, + "id": 5, "interval": 4, - "key": 5, - "repeat": 1, - "texture": 12 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -29566,136 +29566,136 @@ "animations": { "0": { "count": 1, + "first_tile": 80, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 107, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 91, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 91, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 105, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 92, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 92 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 93, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 93 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 94, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 94 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 95, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 95 + "repeat": 0 }, "2": { "count": 10, + "first_tile": 81, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 81 + "repeat": 1 }, "20": { "count": 1, + "first_tile": 64, + "id": 20, "interval": 1, - "key": 20, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "22": { "count": 16, + "first_tile": 64, + "id": 22, "interval": 4, - "key": 22, - "repeat": 1, - "texture": 64 + "repeat": 1 }, "28": { "count": 2, + "first_tile": 105, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 96, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "34": { "count": 1, + "first_tile": 106, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "42": { "count": 5, + "first_tile": 165, + "id": 42, "interval": 4, - "key": 42, - "repeat": 1, - "texture": 165 + "repeat": 1 }, "43": { "count": 5, + "first_tile": 160, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "45": { "count": 1, + "first_tile": 104, + "id": 45, "interval": 1, - "key": 45, - "repeat": 0, - "texture": 104 + "repeat": 0 }, "46": { "count": 2, + "first_tile": 104, + "id": 46, "interval": 8, - "key": 46, - "repeat": 1, - "texture": 104 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -29728,31 +29728,31 @@ "animations": { "0": { "count": 1, + "first_tile": 162, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 162 + "repeat": 0 }, "19": { "count": 6, + "first_tile": 176, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 176 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 160, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "45": { "count": 6, + "first_tile": 182, + "id": 45, "interval": 6, - "key": 45, - "repeat": 0, - "texture": 182 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -29785,59 +29785,59 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 1, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 8, + "id": 2, "interval": 8, - "key": 2, - "repeat": 1, - "texture": 8 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 5, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 5 + "repeat": 0 }, "38": { "count": 2, + "first_tile": 19, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 19 + "repeat": 0 }, "39": { "count": -3, + "first_tile": 20, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 20 + "repeat": 0 }, "40": { "count": 2, + "first_tile": 16, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 8, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 8 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -29870,10 +29870,10 @@ "animations": { "2": { "count": 3, + "first_tile": 189, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 189 + "repeat": 1 } }, "attachOffsetX": 0.35, @@ -29906,17 +29906,17 @@ "animations": { "0": { "count": 1, + "first_tile": 119, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 119 + "repeat": 0 }, "41": { "count": 5, + "first_tile": 116, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 116 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -29949,17 +29949,17 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 0, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 0 + "repeat": 1 } }, "attachOffsetX": 0.35, @@ -29992,10 +29992,10 @@ "animations": { "2": { "count": 4, + "first_tile": 65, + "id": 2, "interval": 7, - "key": 2, - "repeat": 1, - "texture": 65 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -30028,24 +30028,24 @@ "animations": { "2": { "count": 4, + "first_tile": 40, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 40 + "repeat": 1 }, "28": { "count": 4, + "first_tile": 36, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 44, + "id": 5, "interval": 6, - "key": 5, - "repeat": 1, - "texture": 44 + "repeat": 1 } }, "attachOffsetX": 0.35, @@ -30078,17 +30078,17 @@ "animations": { "0": { "count": 1, + "first_tile": 53, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 53 + "repeat": 0 }, "41": { "count": 5, + "first_tile": 48, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 48 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -30121,31 +30121,31 @@ "animations": { "0": { "count": 1, + "first_tile": 117, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 117 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 121, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "2": { "count": 4, + "first_tile": 117, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 117 + "repeat": 1 }, "5": { "count": 7, + "first_tile": 121, + "id": 5, "interval": 4, - "key": 5, - "repeat": 1, - "texture": 121 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -30178,17 +30178,17 @@ "animations": { "0": { "count": 1, + "first_tile": 233, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 233 + "repeat": 0 }, "41": { "count": 6, + "first_tile": 234, + "id": 41, "interval": 2, - "key": 41, - "repeat": 1, - "texture": 234 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -30221,38 +30221,38 @@ "animations": { "0": { "count": 1, + "first_tile": 54, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 54 + "repeat": 0 }, "10": { "count": 1, + "first_tile": 74, + "id": 10, "interval": 1, - "key": 10, - "repeat": 0, - "texture": 74 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 55, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 55 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 70, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 73, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 73 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -30285,31 +30285,31 @@ "animations": { "0": { "count": 4, + "first_tile": 80, + "id": 0, "interval": 5, - "key": 0, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "2": { "count": 5, + "first_tile": 84, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 84 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 89, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 89 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 89, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 89 + "repeat": 0 } }, "attachOffsetX": 0.2, @@ -30342,17 +30342,17 @@ "animations": { "0": { "count": 1, + "first_tile": 63, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 63 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 26, + "id": 2, "interval": 7, - "key": 2, - "repeat": 1, - "texture": 26 + "repeat": 1 } }, "attachOffsetX": 0.35, @@ -30385,73 +30385,73 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 137, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 137 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 137, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 137 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 138, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 138 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 139, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 140, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 140 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 141, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 144, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 129, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 129, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 129 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -30484,52 +30484,52 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "10": { "count": 6, + "first_tile": 10, + "id": 10, "interval": 6, - "key": 10, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "2": { "count": 7, + "first_tile": 1, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 13, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "27": { "count": 3, + "first_tile": 8, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 8 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 10, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 9, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 9 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -30562,45 +30562,45 @@ "animations": { "0": { "count": 5, + "first_tile": 96, + "id": 0, "interval": 8, - "key": 0, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "2": { "count": 5, + "first_tile": 248, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 248 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 101, + "id": 27, "interval": 6, - "key": 27, - "repeat": 0, - "texture": 101 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 102, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 102 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 106, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "45": { "count": 5, + "first_tile": 112, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 112 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -30633,31 +30633,31 @@ "animations": { "19": { "count": 5, + "first_tile": 54, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 54 + "repeat": 0 }, "27": { "count": 5, + "first_tile": 58, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 58 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 48, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 48, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 48 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -30690,38 +30690,38 @@ "animations": { "0": { "count": 1, + "first_tile": 241, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 241 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 242, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 242 + "repeat": 1 }, "27": { "count": -3, + "first_tile": 249, + "id": 27, "interval": 5, - "key": 27, - "repeat": 0, - "texture": 249 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 247, + "id": 28, "interval": 5, - "key": 28, - "repeat": 0, - "texture": 247 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 250, + "id": 41, "interval": 3, - "key": 41, - "repeat": 1, - "texture": 250 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -30754,59 +30754,59 @@ "animations": { "0": { "count": 4, + "first_tile": 192, + "id": 0, "interval": 6, - "key": 0, - "repeat": 2, - "texture": 192 + "repeat": 2 }, "2": { "count": 7, + "first_tile": 249, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 249 + "repeat": 1 }, "27": { "count": 4, + "first_tile": 219, + "id": 27, "interval": 8, - "key": 27, - "repeat": 0, - "texture": 219 + "repeat": 0 }, "28": { "count": 4, + "first_tile": 215, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 215 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 196, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 196 + "repeat": 0 }, "39": { "count": 1, + "first_tile": 235, + "id": 39, "interval": 1, - "key": 39, - "repeat": 0, - "texture": 235 + "repeat": 0 }, "40": { "count": 4, + "first_tile": 231, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 231 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 196, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 196 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -30839,38 +30839,38 @@ "animations": { "0": { "count": 1, + "first_tile": 23, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 23 + "repeat": 0 }, "19": { "count": 7, + "first_tile": 16, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "2": { "count": 7, + "first_tile": 16, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "41": { "count": 7, + "first_tile": 16, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "5": { "count": 6, + "first_tile": 24, + "id": 5, "interval": 4, - "key": 5, - "repeat": 1, - "texture": 24 + "repeat": 1 } }, "attachOffsetX": 0.16, @@ -30903,59 +30903,59 @@ "animations": { "0": { "count": 4, + "first_tile": 176, + "id": 0, "interval": 6, - "key": 0, - "repeat": 2, - "texture": 176 + "repeat": 2 }, "2": { "count": 7, + "first_tile": 242, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 242 + "repeat": 1 }, "27": { "count": 4, + "first_tile": 187, + "id": 27, "interval": 8, - "key": 27, - "repeat": 0, - "texture": 187 + "repeat": 0 }, "28": { "count": 4, + "first_tile": 183, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 183 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 180, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 180 + "repeat": 0 }, "39": { "count": 1, + "first_tile": 203, + "id": 39, "interval": 1, - "key": 39, - "repeat": 0, - "texture": 203 + "repeat": 0 }, "40": { "count": 4, + "first_tile": 199, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 199 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 180, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 180 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -30988,17 +30988,17 @@ "animations": { "22": { "count": 3, + "first_tile": 11, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 7, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 7 + "repeat": 1 } }, "attachOffsetX": 0.0, @@ -31031,17 +31031,17 @@ "animations": { "22": { "count": 3, + "first_tile": 11, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 7, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 7 + "repeat": 1 } }, "attachOffsetX": 0.0, @@ -31074,24 +31074,24 @@ "animations": { "12": { "count": 1, + "first_tile": 11, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 8, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 8 + "repeat": 0 }, "41": { "count": 8, + "first_tile": 0, + "id": 41, "interval": 5, - "key": 41, - "repeat": 1, - "texture": 0 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -31124,24 +31124,24 @@ "animations": { "12": { "count": 1, + "first_tile": 30, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 30 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 35, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 35 + "repeat": 0 }, "41": { "count": 6, + "first_tile": 24, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 24 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -31174,24 +31174,24 @@ "animations": { "12": { "count": 1, + "first_tile": 22, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 22 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 32, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "41": { "count": 6, + "first_tile": 16, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 16 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -31224,24 +31224,24 @@ "animations": { "12": { "count": 1, + "first_tile": 31, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 31 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 20, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 20 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 16, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 16 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -31274,24 +31274,24 @@ "animations": { "12": { "count": 1, + "first_tile": 47, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 47 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 36, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 32, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 32 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -31324,24 +31324,24 @@ "animations": { "12": { "count": 1, + "first_tile": 15, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 15 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 4, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 4 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 0, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 0 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -31374,24 +31374,24 @@ "animations": { "12": { "count": 1, + "first_tile": 63, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 63 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 52, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 52 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 48, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 48 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -31424,24 +31424,24 @@ "animations": { "2": { "count": 4, + "first_tile": 4, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 4 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 1, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "32": { "count": 4, + "first_tile": 4, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 4 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -31474,24 +31474,24 @@ "animations": { "22": { "count": 3, + "first_tile": 48, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "41": { "count": 5, + "first_tile": 40, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 40 + "repeat": 1 }, "45": { "count": 1, + "first_tile": 49, + "id": 45, "interval": 1, - "key": 45, - "repeat": 0, - "texture": 49 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -31524,31 +31524,31 @@ "animations": { "0": { "count": 3, + "first_tile": 0, + "id": 0, "interval": 8, - "key": 0, - "repeat": 2, - "texture": 0 + "repeat": 2 }, "13": { "count": 2, + "first_tile": 3, + "id": 13, "interval": 7, - "key": 13, - "repeat": 0, - "texture": 3 + "repeat": 0 }, "3": { "count": 2, + "first_tile": 3, + "id": 3, "interval": 7, - "key": 3, - "repeat": 0, - "texture": 3 + "repeat": 0 }, "9": { "count": -2, + "first_tile": 4, + "id": 9, "interval": 4, - "key": 9, - "repeat": 0, - "texture": 4 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -31581,45 +31581,45 @@ "animations": { "0": { "count": 4, + "first_tile": 32, + "id": 0, "interval": 6, - "key": 0, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "14": { "count": 1, + "first_tile": 40, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 40 + "repeat": 0 }, "19": { "count": 6, + "first_tile": 48, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "2": { "count": 4, + "first_tile": 36, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 36 + "repeat": 1 }, "3": { "count": 3, + "first_tile": 44, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 44 + "repeat": 0 }, "5": { "count": 5, + "first_tile": 40, + "id": 5, "interval": 6, - "key": 5, - "repeat": 0, - "texture": 40 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -31652,31 +31652,31 @@ "animations": { "0": { "count": 1, + "first_tile": 158, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 158 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 166, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 166 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 159, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 159 + "repeat": 0 }, "9": { "count": 3, + "first_tile": 172, + "id": 9, "interval": 4, - "key": 9, - "repeat": 0, - "texture": 172 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -31709,45 +31709,45 @@ "animations": { "0": { "count": 1, + "first_tile": 154, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 154 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 143, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "32": { "count": 5, + "first_tile": 154, + "id": 32, "interval": 8, - "key": 32, - "repeat": 1, - "texture": 154 + "repeat": 1 }, "41": { "count": 5, + "first_tile": 138, + "id": 41, "interval": 8, - "key": 41, - "repeat": 1, - "texture": 138 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 143, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "8": { "count": 1, + "first_tile": 138, + "id": 8, "interval": 1, - "key": 8, - "repeat": 0, - "texture": 138 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -31780,52 +31780,52 @@ "animations": { "0": { "count": 1, + "first_tile": 230, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 230, + "id": 14, "interval": 6, - "key": 14, - "repeat": 1, - "texture": 230 + "repeat": 1 }, "19": { "count": 3, + "first_tile": 237, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 237 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 215, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 215 + "repeat": 1 }, "3": { "count": 3, + "first_tile": 220, + "id": 3, "interval": 2, - "key": 3, - "repeat": 0, - "texture": 220 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 222, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 222 + "repeat": 0 }, "6": { "count": 3, + "first_tile": 234, + "id": 6, "interval": 4, - "key": 6, - "repeat": 0, - "texture": 234 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -31858,129 +31858,129 @@ "animations": { "0": { "count": 1, + "first_tile": 40, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 40 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 15, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 15 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 15, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 15 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 107, + "id": 14, "interval": 5, - "key": 14, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 12, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 11, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 14, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 14 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 13, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 69, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 69 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 40, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 40 + "repeat": 1 }, "25": { "count": 2, + "first_tile": 240, + "id": 25, "interval": 5, - "key": 25, - "repeat": 0, - "texture": 240 + "repeat": 0 }, "26": { "count": 2, + "first_tile": 246, + "id": 26, "interval": 5, - "key": 26, - "repeat": 0, - "texture": 246 + "repeat": 0 }, "27": { "count": 6, + "first_tile": 57, + "id": 27, "interval": 6, - "key": 27, - "repeat": 0, - "texture": 57 + "repeat": 0 }, "28": { "count": 6, + "first_tile": 52, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 52 + "repeat": 0 }, "33": { "count": 4, + "first_tile": 242, + "id": 33, "interval": 5, - "key": 33, - "repeat": 0, - "texture": 242 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 224, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "8": { "count": 8, + "first_tile": 225, + "id": 8, "interval": 7, - "key": 8, - "repeat": 1, - "texture": 225 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 52, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 52 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -32013,101 +32013,101 @@ "animations": { "0": { "count": 1, + "first_tile": 105, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 121, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 121, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 121, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 121, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 121, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 121, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 121, + "id": 19, "interval": 3, - "key": 19, - "repeat": 1, - "texture": 121 + "repeat": 1 }, "2": { "count": 7, + "first_tile": 105, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 105 + "repeat": 1 }, "27": { "count": 4, + "first_tile": 204, + "id": 27, "interval": 8, - "key": 27, - "repeat": 0, - "texture": 204 + "repeat": 0 }, "28": { "count": 4, + "first_tile": 200, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 200 + "repeat": 0 }, "3": { "count": 2, + "first_tile": 125, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 125 + "repeat": 0 }, "32": { "count": 7, + "first_tile": 105, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 105 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 126, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 126 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -32168,115 +32168,115 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 9, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 64, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 73, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 73 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 73, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 73 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 69, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 69 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 70, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 71, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 71 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 72, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 72 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 160, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 160, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 1, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 160, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 160 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 112, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 112, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 112 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -32365,17 +32365,17 @@ "animations": { "34": { "count": 6, + "first_tile": 4, + "id": 34, "interval": 4, - "key": 34, - "repeat": 1, - "texture": 4 + "repeat": 1 }, "41": { "count": 6, + "first_tile": 20, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 20 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -32408,38 +32408,38 @@ "animations": { "0": { "count": 5, + "first_tile": 0, + "id": 0, "interval": 8, - "key": 0, - "repeat": 1, - "texture": 0 + "repeat": 1 }, "2": { "count": 4, + "first_tile": 220, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 220 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 5, + "id": 27, "interval": 6, - "key": 27, - "repeat": 0, - "texture": 5 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 6, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 6 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 10, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 10 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -32472,17 +32472,17 @@ "animations": { "0": { "count": 1, + "first_tile": 96, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 97, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 97 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -32543,31 +32543,31 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 8, + "id": 2, "interval": 8, - "key": 2, - "repeat": 1, - "texture": 8 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 13, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "41": { "count": 7, + "first_tile": 1, + "id": 41, "interval": 5, - "key": 41, - "repeat": 1, - "texture": 1 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -32600,80 +32600,80 @@ "animations": { "0": { "count": 1, + "first_tile": 24, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 24 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 37, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 37 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 28, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 28 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 24, + "id": 2, "interval": 1, - "key": 2, - "repeat": 0, - "texture": 24 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 21, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 21 + "repeat": 0 }, "3": { "count": 2, + "first_tile": 38, + "id": 3, "interval": 10, - "key": 3, - "repeat": 0, - "texture": 38 + "repeat": 0 }, "31": { "count": 3, + "first_tile": 25, + "id": 31, "interval": 8, - "key": 31, - "repeat": 0, - "texture": 25 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 24, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 24 + "repeat": 0 }, "45": { "count": 6, + "first_tile": 32, + "id": 45, "interval": 5, - "key": 45, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "46": { "count": -6, + "first_tile": 37, + "id": 46, "interval": 5, - "key": 46, - "repeat": 0, - "texture": 37 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 38, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 38 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -32706,73 +32706,73 @@ "animations": { "0": { "count": 1, + "first_tile": 208, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 208 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 47, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 47 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 47, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 47 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 60, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 60 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 61, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 61 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 62, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 62 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 63, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 63 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 28, + "id": 19, "interval": 4, - "key": 19, - "repeat": 2, - "texture": 28 + "repeat": 2 }, "2": { "count": 8, + "first_tile": 209, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 209 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 209, + "id": 32, "interval": 4, - "key": 32, - "repeat": 1, - "texture": 209 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -32805,24 +32805,24 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 33, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 24, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 24 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -32855,52 +32855,52 @@ "animations": { "0": { "count": 4, + "first_tile": 228, + "id": 0, "interval": 6, - "key": 0, - "repeat": 1, - "texture": 228 + "repeat": 1 }, "13": { "count": 5, + "first_tile": 232, + "id": 13, "interval": 6, - "key": 13, - "repeat": 0, - "texture": 232 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 240, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 240 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 232, + "id": 27, "interval": 6, - "key": 27, - "repeat": 0, - "texture": 232 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 225, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 225 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 224, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 224, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 224 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -32933,59 +32933,59 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 143, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 143, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 143, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 143, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 143, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "19": { "count": 7, + "first_tile": 136, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 136 + "repeat": 1 }, "2": { "count": 8, + "first_tile": 128, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 128 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -33018,59 +33018,59 @@ "animations": { "0": { "count": 1, + "first_tile": 210, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 210 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 223, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 223 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 223, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 223 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 219, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 219 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 220, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 220 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 221, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 221 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 222, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 222 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 211, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 211 + "repeat": 1 } }, "attachOffsetX": 0.15, @@ -33159,115 +33159,115 @@ "animations": { "0": { "count": 1, + "first_tile": 224, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 255, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 255 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 240, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 240 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 237, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 237 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 237, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 237 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 233, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 233 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 234, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 234 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 235, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 235 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 236, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 236 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 225, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 225 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 245, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 245 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 245, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 245 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 225, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 225 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 245, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 245 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 218, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 218 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 218, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 218 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -33300,101 +33300,101 @@ "animations": { "0": { "count": 1, + "first_tile": 64, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 77, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 77 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 77, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 77 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 73, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 73 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 74, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 74 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 75, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 75 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 76, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 76 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 65, + "id": 2, "interval": 3, - "key": 2, - "repeat": 1, - "texture": 65 + "repeat": 1 }, "27": { "count": 4, + "first_tile": 101, + "id": 27, "interval": 3, - "key": 27, - "repeat": 0, - "texture": 101 + "repeat": 0 }, "28": { "count": 4, + "first_tile": 91, + "id": 28, "interval": 3, - "key": 28, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 87, + "id": 29, "interval": 3, - "key": 29, - "repeat": 1, - "texture": 87 + "repeat": 1 }, "3": { "count": 3, + "first_tile": 80, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "30": { "count": 4, + "first_tile": 83, + "id": 30, "interval": 3, - "key": 30, - "repeat": 1, - "texture": 83 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 65, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 65 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -33427,31 +33427,31 @@ "animations": { "0": { "count": 1, + "first_tile": 208, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 208 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 211, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 211 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 209, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 209 + "repeat": 0 }, "8": { "count": 1, + "first_tile": 210, + "id": 8, "interval": 1, - "key": 8, - "repeat": 0, - "texture": 210 + "repeat": 0 } }, "attachOffsetX": 0.0, @@ -33484,17 +33484,17 @@ "animations": { "19": { "count": 1, + "first_tile": 240, + "id": 19, "interval": 1, - "key": 19, - "repeat": 0, - "texture": 240 + "repeat": 0 }, "41": { "count": 6, + "first_tile": 224, + "id": 41, "interval": 2, - "key": 41, - "repeat": 1, - "texture": 224 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -33527,31 +33527,31 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "19": { "count": 12, + "first_tile": 19, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 19 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 8, + "id": 2, "interval": 8, - "key": 2, - "repeat": 1, - "texture": 8 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 16, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 16 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -33584,80 +33584,80 @@ "animations": { "0": { "count": 1, + "first_tile": 192, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 192 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 205, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 205 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 205, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 205 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 201, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 201 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 202, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 202 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 203, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 203 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 204, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 204 + "repeat": 0 }, "19": { "count": 2, + "first_tile": 212, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 212 + "repeat": 0 }, "2": { "count": 9, + "first_tile": 192, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 192 + "repeat": 1 }, "45": { "count": 2, + "first_tile": 208, + "id": 45, "interval": 6, - "key": 45, - "repeat": 0, - "texture": 208 + "repeat": 0 }, "46": { "count": 2, + "first_tile": 210, + "id": 46, "interval": 6, - "key": 46, - "repeat": 1, - "texture": 210 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -33690,80 +33690,80 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 68, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 68 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 68, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 68 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 64, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 65, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 65 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 66, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 66 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 67, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 67 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 80, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 32, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "3": { "count": 4, + "first_tile": 48, + "id": 3, "interval": 2, - "key": 3, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 32, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 32 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -33796,115 +33796,115 @@ "animations": { "0": { "count": 1, + "first_tile": 176, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 176 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 207, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 207 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 192, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 192 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 189, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 189 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 189, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 189 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 185, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 185 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 186, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 186 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 187, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 187 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 188, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 188 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 177, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 177 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 197, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 197 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 197, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 197 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 177, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 177 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 197, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 197 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 170, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 170 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 170, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 170 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -33937,87 +33937,87 @@ "animations": { "0": { "count": 1, + "first_tile": 112, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 126, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 126, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 122, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 123, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 123 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 124, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 125, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 125 + "repeat": 0 }, "19": { "count": 1, + "first_tile": 121, + "id": 19, "interval": 1, - "key": 19, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 113, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "3": { "count": 2, + "first_tile": 119, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 119 + "repeat": 0 }, "32": { "count": 6, + "first_tile": 113, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "34": { "count": 1, + "first_tile": 112, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 112 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -34050,87 +34050,87 @@ "animations": { "0": { "count": 1, + "first_tile": 112, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 126, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 126, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 122, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 123, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 123 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 124, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 125, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 125 + "repeat": 0 }, "19": { "count": 1, + "first_tile": 121, + "id": 19, "interval": 1, - "key": 19, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 113, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "3": { "count": 2, + "first_tile": 119, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 119 + "repeat": 0 }, "32": { "count": 6, + "first_tile": 113, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "34": { "count": 1, + "first_tile": 112, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 112 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -34163,87 +34163,87 @@ "animations": { "0": { "count": 1, + "first_tile": 112, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 126, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 126, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 122, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 123, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 123 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 124, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 125, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 125 + "repeat": 0 }, "19": { "count": 1, + "first_tile": 121, + "id": 19, "interval": 1, - "key": 19, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 113, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "3": { "count": 2, + "first_tile": 119, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 119 + "repeat": 0 }, "32": { "count": 6, + "first_tile": 113, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "34": { "count": 1, + "first_tile": 112, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 112 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -34276,17 +34276,17 @@ "animations": { "19": { "count": 4, + "first_tile": 0, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 0, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "attachOffsetX": -2.5, @@ -34319,24 +34319,24 @@ "animations": { "12": { "count": 1, + "first_tile": 1, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 2, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 2 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 0, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -34369,108 +34369,108 @@ "animations": { "0": { "count": 1, + "first_tile": 48, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "11": { "count": 12, + "first_tile": 84, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 84 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 57, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 57 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 57, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 57 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 60, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 60 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 61, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 61 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 62, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 62 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 63, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 63 + "repeat": 0 }, "19": { "count": 12, + "first_tile": 72, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 72 + "repeat": 1 }, "2": { "count": 8, + "first_tile": 49, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 49 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 64, + "id": 23, "interval": 4, - "key": 23, - "repeat": 1, - "texture": 64 + "repeat": 1 }, "3": { "count": 5, + "first_tile": 49, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 49 + "repeat": 0 }, "43": { "count": 2, + "first_tile": 58, + "id": 43, "interval": 4, - "key": 43, - "repeat": 0, - "texture": 58 + "repeat": 0 }, "44": { "count": -2, + "first_tile": 59, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 59 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 53, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 53 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -34503,108 +34503,108 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "11": { "count": 12, + "first_tile": 36, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 12, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 13, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 14, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 14 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 15, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 15 + "repeat": 0 }, "19": { "count": 12, + "first_tile": 24, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 24 + "repeat": 1 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 16, + "id": 23, "interval": 4, - "key": 23, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "3": { "count": 5, + "first_tile": 1, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "43": { "count": 2, + "first_tile": 10, + "id": 43, "interval": 4, - "key": 43, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "44": { "count": -2, + "first_tile": 11, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 5, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 5 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -34637,108 +34637,108 @@ "animations": { "0": { "count": 1, + "first_tile": 96, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "11": { "count": 12, + "first_tile": 132, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 132 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 105, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 105, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 108, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 108 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 109, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 109 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 110, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 110 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 111, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 111 + "repeat": 0 }, "19": { "count": 12, + "first_tile": 120, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 120 + "repeat": 1 }, "2": { "count": 8, + "first_tile": 97, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 97 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 112, + "id": 23, "interval": 4, - "key": 23, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "3": { "count": 5, + "first_tile": 97, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 97 + "repeat": 0 }, "43": { "count": 2, + "first_tile": 106, + "id": 43, "interval": 4, - "key": 43, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "44": { "count": -2, + "first_tile": 107, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 101, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 101 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -34771,87 +34771,87 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 12, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 13, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 14, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 14 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 15, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 15 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 16, + "id": 23, "interval": 4, - "key": 23, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "3": { "count": 5, + "first_tile": 1, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 5, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 5 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -34884,66 +34884,66 @@ "animations": { "0": { "count": 5, + "first_tile": 32, + "id": 0, "interval": 4, - "key": 0, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "10": { "count": 5, + "first_tile": 21, + "id": 10, "interval": 4, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 47, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 47 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 43, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 44, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 44 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 45, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 45 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 46, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 46 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 37, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 37 + "repeat": 1 }, "45": { "count": 3, + "first_tile": 26, + "id": 45, "interval": 5, - "key": 45, - "repeat": 1, - "texture": 26 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -34976,10 +34976,10 @@ "animations": { "41": { "count": 6, + "first_tile": 56, + "id": 41, "interval": 2, - "key": 41, - "repeat": 1, - "texture": 56 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -35012,31 +35012,31 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "2": { "count": 9, + "first_tile": 37, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 37 + "repeat": 1 }, "3": { "count": 4, + "first_tile": 33, + "id": 3, "interval": 8, - "key": 3, - "repeat": 0, - "texture": 33 + "repeat": 0 }, "5": { "count": -4, + "first_tile": 36, + "id": 5, "interval": 8, - "key": 5, - "repeat": 0, - "texture": 36 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -35069,38 +35069,38 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 16, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "2": { "count": 4, + "first_tile": 0, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 0 + "repeat": 1 }, "22": { "count": 4, + "first_tile": 32, + "id": 22, "interval": 4, - "key": 22, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "32": { "count": 4, + "first_tile": 0, + "id": 32, "interval": 4, - "key": 32, - "repeat": 1, - "texture": 0 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -35133,10 +35133,10 @@ "animations": { "2": { "count": 4, + "first_tile": 92, + "id": 2, "interval": 2, - "key": 2, - "repeat": 1, - "texture": 92 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -35169,38 +35169,38 @@ "animations": { "0": { "count": 5, + "first_tile": 192, + "id": 0, "interval": 6, - "key": 0, - "repeat": 1, - "texture": 192 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 213, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 213 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 197, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 197 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 208, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 208 + "repeat": 1 }, "3": { "count": 4, + "first_tile": 197, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 197 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -35233,115 +35233,115 @@ "animations": { "0": { "count": 1, + "first_tile": 96, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 127, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 127 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 112, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 109, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 109 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 109, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 109 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 105, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 106, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 107, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 108, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 108 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 97, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 97 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 117, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 117 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 117, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 117 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 97, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 97 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 117, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 117 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 90, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 90 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 90, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 90 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -35374,108 +35374,108 @@ "animations": { "0": { "count": 1, + "first_tile": 96, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 112, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 109, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 109 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 109, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 109 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 105, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 106, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 107, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 108, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 108 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 97, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 97 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 117, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 117 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 117, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 117 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 97, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 97 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 117, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 117 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 90, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 90 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 90, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 90 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -35508,115 +35508,115 @@ "animations": { "0": { "count": 1, + "first_tile": 80, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 111, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 111 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 96, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 93, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 93 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 93, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 93 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 89, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 89 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 90, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 90 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 91, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 92, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 92 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 81, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 81 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 101, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 101 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 101, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 101 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 81, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 81 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 101, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 101 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 74, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 74 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 74, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 74 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -35649,115 +35649,115 @@ "animations": { "0": { "count": 1, + "first_tile": 176, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 176 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 207, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 207 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 192, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 192 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 189, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 189 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 189, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 189 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 185, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 185 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 186, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 186 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 187, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 187 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 188, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 188 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 177, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 177 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 197, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 197 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 197, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 197 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 177, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 177 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 197, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 197 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 170, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 170 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 170, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 170 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -35790,115 +35790,115 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 159, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 159 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 144, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 141, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 141, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 137, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 137 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 138, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 138 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 139, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 140, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 140 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 129, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 149, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 149 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 149, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 149 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 129, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 149, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 149 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 122, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 122, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 122 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -35931,31 +35931,31 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "2": { "count": 9, + "first_tile": 37, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 37 + "repeat": 1 }, "3": { "count": 4, + "first_tile": 33, + "id": 3, "interval": 8, - "key": 3, - "repeat": 0, - "texture": 33 + "repeat": 0 }, "5": { "count": -4, + "first_tile": 36, + "id": 5, "interval": 8, - "key": 5, - "repeat": 0, - "texture": 36 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -35988,24 +35988,24 @@ "animations": { "0": { "count": 1, + "first_tile": 2, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 2 + "repeat": 0 }, "19": { "count": 6, + "first_tile": 16, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 0, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 0 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -36038,80 +36038,80 @@ "animations": { "0": { "count": 1, + "first_tile": 149, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 149 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 173, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 173 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 173, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 173 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 158, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 158 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 159, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 159 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 174, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 174 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 175, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 175 + "repeat": 0 }, "19": { "count": 7, + "first_tile": 166, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 166 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 150, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 150 + "repeat": 1 }, "3": { "count": 5, + "first_tile": 160, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 160 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 165, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 165 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -36144,38 +36144,38 @@ "animations": { "0": { "count": 1, + "first_tile": 48, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 56, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 48, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "3": { "count": 3, + "first_tile": 53, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 53 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 57, + "id": 5, "interval": 8, - "key": 5, - "repeat": 0, - "texture": 57 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -36208,38 +36208,38 @@ "animations": { "0": { "count": 1, + "first_tile": 8, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 8 + "repeat": 0 }, "11": { "count": 1, + "first_tile": 9, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 9, + "id": 2, "interval": 1, - "key": 2, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 4, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 4 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 9, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 9 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -36272,31 +36272,31 @@ "animations": { "0": { "count": 1, + "first_tile": 208, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 208 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 105, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 209, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 209 + "repeat": 1 }, "5": { "count": 6, + "first_tile": 106, + "id": 5, "interval": 4, - "key": 5, - "repeat": 1, - "texture": 106 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -36329,115 +36329,115 @@ "animations": { "0": { "count": 1, + "first_tile": 16, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 47, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 47 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 32, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 29, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 29 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 29, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 29 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 25, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 25 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 26, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 26 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 27, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 27 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 28, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 28 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 17, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 17 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 37, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 37 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 37, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 37 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 17, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 17 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 37, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 37 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 10, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 10, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 10 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -36498,80 +36498,80 @@ "animations": { "0": { "count": 1, + "first_tile": 144, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 160, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 160 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 153, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 153 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 153, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 153 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 154, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 154 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 155, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 155 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 156, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 156 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 157, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 157 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 145, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 145 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 145, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 145 + "repeat": 1 }, "43": { "count": 5, + "first_tile": 10, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 10 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -36604,31 +36604,31 @@ "animations": { "13": { "count": 1, + "first_tile": 141, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 136, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 136 + "repeat": 0 }, "41": { "count": 8, + "first_tile": 128, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 128 + "repeat": 1 }, "5": { "count": 8, + "first_tile": 128, + "id": 5, "interval": 6, - "key": 5, - "repeat": 1, - "texture": 128 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -36661,101 +36661,101 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 22, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 22 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 10, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 11, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 13, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 12, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 14, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 14 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "41": { "count": 6, + "first_tile": 16, + "id": 41, "interval": 3, - "key": 41, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "5": { "count": 8, + "first_tile": 1, + "id": 5, "interval": 3, - "key": 5, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "9": { "count": 6, + "first_tile": 22, + "id": 9, "interval": 4, - "key": 9, - "repeat": 0, - "texture": 22 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -36788,101 +36788,101 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 41, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 41 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 41, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 41 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 54, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 54 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 42, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 42 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 43, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 45, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 45 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 44, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 44 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 33, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 46, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 46 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 33, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "41": { "count": 6, + "first_tile": 48, + "id": 41, "interval": 3, - "key": 41, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "5": { "count": 8, + "first_tile": 33, + "id": 5, "interval": 3, - "key": 5, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "9": { "count": 6, + "first_tile": 54, + "id": 9, "interval": 4, - "key": 9, - "repeat": 0, - "texture": 54 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -36915,87 +36915,87 @@ "animations": { "0": { "count": 1, + "first_tile": 176, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 176 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 185, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 185 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 185, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 185 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 186, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 186 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 187, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 187 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 188, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 188 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 189, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 189 + "repeat": 0 }, "19": { "count": 3, + "first_tile": 169, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 169 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 177, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 177 + "repeat": 1 }, "43": { "count": 5, + "first_tile": 96, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "45": { "count": 1, + "first_tile": 165, + "id": 45, "interval": 40, - "key": 45, - "repeat": 0, - "texture": 165 + "repeat": 0 }, "46": { "count": 3, + "first_tile": 166, + "id": 46, "interval": 6, - "key": 46, - "repeat": 1, - "texture": 166 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -37028,17 +37028,17 @@ "animations": { "22": { "count": 4, + "first_tile": 196, + "id": 22, "interval": 8, - "key": 22, - "repeat": 0, - "texture": 196 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 192, + "id": 41, "interval": 8, - "key": 41, - "repeat": 1, - "texture": 192 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -37099,115 +37099,115 @@ "animations": { "0": { "count": 1, + "first_tile": 224, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 255, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 255 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 240, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 240 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 237, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 237 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 237, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 237 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 233, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 233 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 234, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 234 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 235, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 235 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 236, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 236 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 225, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 225 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 245, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 245 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 245, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 245 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 225, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 225 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 245, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 245 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 218, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 218 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 218, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 218 + "repeat": 1 } }, "attachOffsetX": 0.25, @@ -37240,80 +37240,80 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 13, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 13, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 9, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 10, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 11, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 12, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 16, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 0, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "5": { "count": 5, + "first_tile": 75, + "id": 5, "interval": 3, - "key": 5, - "repeat": 0, - "texture": 75 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -37346,66 +37346,66 @@ "animations": { "0": { "count": 1, + "first_tile": 16, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 20, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 20 + "repeat": 0 }, "19": { "count": 3, + "first_tile": 21, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 21 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 32, + "id": 2, "interval": 8, - "key": 2, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 17, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 17 + "repeat": 0 }, "38": { "count": 3, + "first_tile": 29, + "id": 38, "interval": 4, - "key": 38, - "repeat": 1, - "texture": 29 + "repeat": 1 }, "39": { "count": 2, + "first_tile": 38, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 38 + "repeat": 0 }, "40": { "count": 5, + "first_tile": 24, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 24 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 16, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 16 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -37438,66 +37438,66 @@ "animations": { "0": { "count": 1, + "first_tile": 40, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 40 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 44, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 44 + "repeat": 0 }, "19": { "count": 3, + "first_tile": 45, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 45 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 56, + "id": 2, "interval": 8, - "key": 2, - "repeat": 1, - "texture": 56 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 41, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 41 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 51, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 51 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 48, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "40": { "count": 3, + "first_tile": 52, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 52 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 40, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 40 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -37530,143 +37530,143 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 149, + "id": 10, "interval": 4, - "key": 10, - "repeat": 1, - "texture": 149 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 141, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 141, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 138, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 138 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 137, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 137 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 140, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 140 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 139, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 160, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 160 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 129, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 176, + "id": 23, "interval": 6, - "key": 23, - "repeat": 0, - "texture": 176 + "repeat": 0 }, "27": { "count": 3, + "first_tile": 144, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 146, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 146 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 182, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 182 + "repeat": 0 }, "32": { "count": 6, + "first_tile": 129, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "41": { "count": 4, + "first_tile": 186, + "id": 41, "interval": 8, - "key": 41, - "repeat": 1, - "texture": 186 + "repeat": 1 }, "45": { "count": 5, + "first_tile": 165, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 165 + "repeat": 0 }, "46": { "count": 5, + "first_tile": 170, + "id": 46, "interval": 4, - "key": 46, - "repeat": 0, - "texture": 170 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 185, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 185 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 146, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 146 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -37755,101 +37755,101 @@ "animations": { "0": { "count": 1, + "first_tile": 21, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 21 + "repeat": 0 }, "10": { "count": 4, + "first_tile": 76, + "id": 10, "interval": 5, - "key": 10, - "repeat": 1, - "texture": 76 + "repeat": 1 }, "13": { "count": 3, + "first_tile": 50, + "id": 13, "interval": 6, - "key": 13, - "repeat": 0, - "texture": 50 + "repeat": 0 }, "19": { "count": 7, + "first_tile": 42, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 42 + "repeat": 0 }, "2": { "count": 12, + "first_tile": 56, + "id": 2, "interval": 10, - "key": 2, - "repeat": 1, - "texture": 56 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 29, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 29 + "repeat": 0 }, "27": { "count": 2, + "first_tile": 50, + "id": 27, "interval": 6, - "key": 27, - "repeat": 0, - "texture": 50 + "repeat": 0 }, "28": { "count": 2, + "first_tile": 53, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 53 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 22, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 22 + "repeat": 0 }, "32": { "count": 12, + "first_tile": 56, + "id": 32, "interval": 7, - "key": 32, - "repeat": 1, - "texture": 56 + "repeat": 1 }, "45": { "count": 1, + "first_tile": 55, + "id": 45, "interval": 6, - "key": 45, - "repeat": 0, - "texture": 55 + "repeat": 0 }, "46": { "count": -4, + "first_tile": 79, + "id": 46, "interval": 5, - "key": 46, - "repeat": 1, - "texture": 79 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 22, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 22 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 52, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 52 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -37882,143 +37882,143 @@ "animations": { "0": { "count": 1, + "first_tile": 192, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 192 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 213, + "id": 10, "interval": 4, - "key": 10, - "repeat": 1, - "texture": 213 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 205, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 205 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 205, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 205 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 202, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 202 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 201, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 201 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 204, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 204 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 203, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 203 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 224, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 193, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 193 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 240, + "id": 23, "interval": 6, - "key": 23, - "repeat": 0, - "texture": 240 + "repeat": 0 }, "27": { "count": 3, + "first_tile": 208, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 208 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 210, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 210 + "repeat": 0 }, "3": { "count": 4, + "first_tile": 246, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 246 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 193, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 193 + "repeat": 1 }, "41": { "count": 1, + "first_tile": 249, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 249 + "repeat": 0 }, "45": { "count": 5, + "first_tile": 229, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 229 + "repeat": 0 }, "46": { "count": 5, + "first_tile": 234, + "id": 46, "interval": 4, - "key": 46, - "repeat": 0, - "texture": 234 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 250, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 250 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 210, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 210 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -38051,143 +38051,143 @@ "animations": { "0": { "count": 1, + "first_tile": 64, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 85, + "id": 10, "interval": 4, - "key": 10, - "repeat": 1, - "texture": 85 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 77, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 77 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 77, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 77 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 74, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 74 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 73, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 73 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 76, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 76 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 75, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 75 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 96, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 65, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 65 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 112, + "id": 23, "interval": 6, - "key": 23, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "27": { "count": 3, + "first_tile": 80, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 82, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 82 + "repeat": 0 }, "3": { "count": 4, + "first_tile": 118, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 118 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 65, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 65 + "repeat": 1 }, "41": { "count": 1, + "first_tile": 121, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "45": { "count": 5, + "first_tile": 101, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 101 + "repeat": 0 }, "46": { "count": 5, + "first_tile": 106, + "id": 46, "interval": 4, - "key": 46, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 122, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 82, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 82 + "repeat": 0 } }, "attachOffsetX": 0.25, @@ -38220,143 +38220,143 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 4, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 13, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 13, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 10, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 9, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 12, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 11, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 44, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 44 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 48, + "id": 23, "interval": 6, - "key": 23, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "3": { "count": 4, + "first_tile": 32, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "41": { "count": 4, + "first_tile": 40, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 40 + "repeat": 1 }, "45": { "count": 4, + "first_tile": 58, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 58 + "repeat": 0 }, "46": { "count": 4, + "first_tile": 54, + "id": 46, "interval": 4, - "key": 46, - "repeat": 0, - "texture": 54 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 36, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "attachOffsetX": 0.25, diff --git a/docs/game_data/entities_texture_only.json b/docs/game_data/entities_texture_only.json index 83af7effe..ed222190a 100644 --- a/docs/game_data/entities_texture_only.json +++ b/docs/game_data/entities_texture_only.json @@ -543,318 +543,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 200, @@ -864,318 +864,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 194, @@ -1185,318 +1185,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 207, @@ -1506,318 +1506,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 198, @@ -1827,318 +1827,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 213, @@ -2148,318 +2148,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 202, @@ -2469,318 +2469,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 196, @@ -2790,318 +2790,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 208, @@ -3111,318 +3111,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 211, @@ -3432,318 +3432,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 216, @@ -3753,318 +3753,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 199, @@ -4074,318 +4074,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 212, @@ -4395,318 +4395,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 215, @@ -4716,318 +4716,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 201, @@ -5037,318 +5037,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 203, @@ -5358,318 +5358,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 195, @@ -5679,318 +5679,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 204, @@ -6000,318 +6000,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 209, @@ -6321,318 +6321,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 210, @@ -6642,318 +6642,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 197, @@ -6963,318 +6963,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 205, @@ -7284,318 +7284,318 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 43, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 3, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "11": { "count": 5, + "first_tile": 70, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 1, - "texture": 9 + "repeat": 1 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 56, + "id": 14, "interval": 4, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 32, + "id": 15, "interval": 1, - "key": 15, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "16": { "count": 1, + "first_tile": 33, + "id": 16, "interval": 1, - "key": 16, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "17": { "count": 1, + "first_tile": 34, + "id": 17, "interval": 1, - "key": 17, - "repeat": 1, - "texture": 34 + "repeat": 1 }, "18": { "count": 1, + "first_tile": 35, + "id": 18, "interval": 1, - "key": 18, - "repeat": 1, - "texture": 35 + "repeat": 1 }, "19": { "count": 6, + "first_tile": 64, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "20": { "count": 8, + "first_tile": 48, + "id": 20, "interval": 4, - "key": 20, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "21": { "count": 7, + "first_tile": 36, + "id": 21, "interval": 4, - "key": 21, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "23": { "count": 6, + "first_tile": 80, + "id": 23, "interval": 6, - "key": 23, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "24": { "count": 6, + "first_tile": 86, + "id": 24, "interval": 6, - "key": 24, - "repeat": 1, - "texture": 86 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 112, + "id": 25, "interval": 4, - "key": 25, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 112, + "id": 26, "interval": 4, - "key": 26, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 128, + "id": 29, "interval": 2, - "key": 29, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 144, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "30": { "count": -4, + "first_tile": 131, + "id": 30, "interval": 2, - "key": 30, - "repeat": 0, - "texture": 131 + "repeat": 0 }, "31": { "count": 6, + "first_tile": 102, + "id": 31, "interval": 4, - "key": 31, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 112, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 135, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "35": { "count": 5, + "first_tile": 135, + "id": 35, "interval": 2, - "key": 35, - "repeat": 0, - "texture": 135 + "repeat": 0 }, "36": { "count": 4, + "first_tile": 139, + "id": 36, "interval": 2, - "key": 36, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "37": { "count": 1, + "first_tile": 121, + "id": 37, "interval": 1, - "key": 37, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "38": { "count": 1, + "first_tile": 124, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 122, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "4": { "count": 6, + "first_tile": 10, + "id": 4, "interval": 6, - "key": 4, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "40": { "count": 3, + "first_tile": 124, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "42": { "count": 2, + "first_tile": 224, + "id": 42, "interval": 4, - "key": 42, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "43": { "count": 4, + "first_tile": 226, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 226 + "repeat": 1 }, "44": { "count": 2, + "first_tile": 230, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "45": { "count": 8, + "first_tile": 48, + "id": 45, "interval": 3, - "key": 45, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "46": { "count": 4, + "first_tile": 152, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 152 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 148, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "6": { "count": 6, + "first_tile": 180, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 180 + "repeat": 1 }, "7": { "count": 1, + "first_tile": 96, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 96, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 206, @@ -8640,10 +8640,10 @@ "animations": { "0": { "count": 12, + "first_tile": 48, + "id": 0, "interval": 4, - "key": 0, - "repeat": 1, - "texture": 48 + "repeat": 1 } }, "id": 636, @@ -8693,10 +8693,10 @@ "animations": { "22": { "count": 3, + "first_tile": 5, + "id": 22, "interval": 4, - "key": 22, - "repeat": 1, - "texture": 5 + "repeat": 1 } }, "id": 683, @@ -8741,10 +8741,10 @@ "animations": { "0": { "count": 16, + "first_tile": 0, + "id": 0, "interval": 2, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "id": 637, @@ -8774,10 +8774,10 @@ "animations": { "3": { "count": 5, + "first_tile": 10, + "id": 3, "interval": 8, - "key": 3, - "repeat": 0, - "texture": 10 + "repeat": 0 } }, "id": 724, @@ -8807,24 +8807,24 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "41": { "count": 3, + "first_tile": 0, + "id": 41, "interval": 5, - "key": 41, - "repeat": 2, - "texture": 0 + "repeat": 2 }, "5": { "count": 3, + "first_tile": 0, + "id": 5, "interval": 8, - "key": 5, - "repeat": 2, - "texture": 0 + "repeat": 2 } }, "id": 723, @@ -8844,10 +8844,10 @@ "animations": { "0": { "count": 3, + "first_tile": 24, + "id": 0, "interval": 2, - "key": 0, - "repeat": 1, - "texture": 24 + "repeat": 1 } }, "id": 657, @@ -8857,31 +8857,31 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 4, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 4 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 25, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 25 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 1, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 1 + "repeat": 0 } }, "id": 685, @@ -8921,10 +8921,10 @@ "animations": { "0": { "count": 8, + "first_tile": 0, + "id": 0, "interval": 4, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "id": 675, @@ -8939,17 +8939,17 @@ "animations": { "0": { "count": 1, + "first_tile": 133, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 133 + "repeat": 0 }, "32": { "count": 5, + "first_tile": 134, + "id": 32, "interval": 4, - "key": 32, - "repeat": 1, - "texture": 134 + "repeat": 1 } }, "id": 684, @@ -9019,10 +9019,10 @@ "animations": { "0": { "count": 16, + "first_tile": 0, + "id": 0, "interval": 2, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "id": 639, @@ -9032,10 +9032,10 @@ "animations": { "0": { "count": 6, + "first_tile": 32, + "id": 0, "interval": 4, - "key": 0, - "repeat": 1, - "texture": 32 + "repeat": 1 } }, "id": 661, @@ -9045,17 +9045,17 @@ "animations": { "0": { "count": 1, + "first_tile": 38, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 38 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 39, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 39 + "repeat": 0 } }, "id": 664, @@ -9130,10 +9130,10 @@ "animations": { "0": { "count": 16, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "id": 638, @@ -9183,10 +9183,10 @@ "animations": { "0": { "count": 5, + "first_tile": 0, + "id": 0, "interval": 2, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "id": 656, @@ -9196,10 +9196,10 @@ "animations": { "0": { "count": 7, + "first_tile": 185, + "id": 0, "interval": 6, - "key": 0, - "repeat": 1, - "texture": 185 + "repeat": 1 } }, "id": 672, @@ -9219,10 +9219,10 @@ "animations": { "0": { "count": 7, + "first_tile": 9, + "id": 0, "interval": 3, - "key": 0, - "repeat": 1, - "texture": 9 + "repeat": 1 } }, "id": 695, @@ -9232,10 +9232,10 @@ "animations": { "0": { "count": 7, + "first_tile": 9, + "id": 0, "interval": 2, - "key": 0, - "repeat": 1, - "texture": 9 + "repeat": 1 } }, "id": 696, @@ -9290,45 +9290,45 @@ "animations": { "0": { "count": 1, + "first_tile": 4, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 4 + "repeat": 0 }, "12": { "count": 3, + "first_tile": 13, + "id": 12, "interval": 4, - "key": 12, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 12, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "19": { "count": 3, + "first_tile": 5, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 5 + "repeat": 0 }, "45": { "count": -3, + "first_tile": 7, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 7 + "repeat": 0 }, "46": { "count": -3, + "first_tile": 15, + "id": 46, "interval": 4, - "key": 46, - "repeat": 0, - "texture": 15 + "repeat": 0 } }, "id": 710, @@ -9398,10 +9398,10 @@ "animations": { "0": { "count": 5, + "first_tile": 59, + "id": 0, "interval": 4, - "key": 0, - "repeat": 0, - "texture": 59 + "repeat": 0 } }, "id": 679, @@ -9421,10 +9421,10 @@ "animations": { "0": { "count": 4, + "first_tile": 24, + "id": 0, "interval": 6, - "key": 0, - "repeat": 1, - "texture": 24 + "repeat": 1 } }, "id": 660, @@ -9524,59 +9524,59 @@ "animations": { "0": { "count": 1, + "first_tile": 116, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 116 + "repeat": 0 }, "10": { "count": 1, + "first_tile": 121, + "id": 10, "interval": 1, - "key": 10, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 40, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 40 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 117, + "id": 2, "interval": 1, - "key": 2, - "repeat": 0, - "texture": 117 + "repeat": 0 }, "22": { "count": 1, + "first_tile": 124, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "32": { "count": 6, + "first_tile": 118, + "id": 32, "interval": 6, - "key": 32, - "repeat": 1, - "texture": 118 + "repeat": 1 }, "5": { "count": 3, + "first_tile": 125, + "id": 5, "interval": 3, - "key": 5, - "repeat": 1, - "texture": 125 + "repeat": 1 }, "6": { "count": 3, + "first_tile": 125, + "id": 6, "interval": 6, - "key": 6, - "repeat": 1, - "texture": 125 + "repeat": 1 } }, "id": 564, @@ -9661,10 +9661,10 @@ "animations": { "41": { "count": 8, + "first_tile": 48, + "id": 41, "interval": 4, - "key": 41, - "repeat": 0, - "texture": 48 + "repeat": 0 } }, "id": 440, @@ -9694,10 +9694,10 @@ "animations": { "22": { "count": 6, + "first_tile": 229, + "id": 22, "interval": 3, - "key": 22, - "repeat": 1, - "texture": 229 + "repeat": 1 } }, "id": 448, @@ -9717,24 +9717,24 @@ "animations": { "0": { "count": 1, + "first_tile": 167, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 167 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 168, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 168 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 169, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 169 + "repeat": 1 } }, "id": 492, @@ -9799,10 +9799,10 @@ "animations": { "41": { "count": 4, + "first_tile": 12, + "id": 41, "interval": 2, - "key": 41, - "repeat": 2, - "texture": 12 + "repeat": 2 } }, "id": 436, @@ -9832,31 +9832,31 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "27": { "count": 2, + "first_tile": 1, + "id": 27, "interval": 2, - "key": 27, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "28": { "count": -2, + "first_tile": 2, + "id": 28, "interval": 2, - "key": 28, - "repeat": 0, - "texture": 2 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 3, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 3 + "repeat": 0 } }, "id": 445, @@ -9866,31 +9866,31 @@ "animations": { "0": { "count": 1, + "first_tile": 102, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 102 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 103, + "id": 2, "interval": 6, - "key": 2, - "repeat": 0, - "texture": 103 + "repeat": 0 }, "45": { "count": 4, + "first_tile": 104, + "id": 45, "interval": 6, - "key": 45, - "repeat": 0, - "texture": 104 + "repeat": 0 }, "46": { "count": 4, + "first_tile": 108, + "id": 46, "interval": 6, - "key": 46, - "repeat": 0, - "texture": 108 + "repeat": 0 } }, "id": 467, @@ -9905,17 +9905,17 @@ "animations": { "0": { "count": 1, + "first_tile": 139, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 139, + "id": 2, "interval": 4, - "key": 2, - "repeat": 0, - "texture": 139 + "repeat": 0 } }, "id": 495, @@ -9925,17 +9925,17 @@ "animations": { "0": { "count": 1, + "first_tile": 155, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 155 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 155, + "id": 2, "interval": 4, - "key": 2, - "repeat": 0, - "texture": 155 + "repeat": 0 } }, "id": 496, @@ -9945,17 +9945,17 @@ "animations": { "0": { "count": 1, + "first_tile": 220, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 220 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 215, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 215 + "repeat": 1 } }, "id": 502, @@ -9995,24 +9995,24 @@ "animations": { "0": { "count": 1, + "first_tile": 149, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 149 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 148, + "id": 2, "interval": 1, - "key": 2, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "5": { "count": 2, + "first_tile": 150, + "id": 5, "interval": 4, - "key": 5, - "repeat": 1, - "texture": 150 + "repeat": 1 } }, "id": 572, @@ -10152,17 +10152,17 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 128, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 128 + "repeat": 0 } }, "id": 582, @@ -10202,10 +10202,10 @@ "animations": { "41": { "count": 8, + "first_tile": 128, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 128 + "repeat": 1 } }, "id": 475, @@ -10435,38 +10435,38 @@ "animations": { "12": { "count": 1, + "first_tile": 186, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 186 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 172, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 172 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 160, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "45": { "count": 4, + "first_tile": 164, + "id": 45, "interval": 2, - "key": 45, - "repeat": 0, - "texture": 164 + "repeat": 0 }, "46": { "count": 2, + "first_tile": 168, + "id": 46, "interval": 4, - "key": 46, - "repeat": 1, - "texture": 168 + "repeat": 1 } }, "id": 446, @@ -10496,17 +10496,17 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 7, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 7 + "repeat": 0 } }, "id": 560, @@ -10756,17 +10756,17 @@ "animations": { "0": { "count": 1, + "first_tile": 199, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 199 + "repeat": 0 }, "19": { "count": 1, + "first_tile": 200, + "id": 19, "interval": 1, - "key": 19, - "repeat": 0, - "texture": 200 + "repeat": 0 } }, "id": 469, @@ -10871,45 +10871,45 @@ "animations": { "0": { "count": 1, + "first_tile": 248, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 248 + "repeat": 0 }, "10": { "count": 1, + "first_tile": 249, + "id": 10, "interval": 10, - "key": 10, - "repeat": 0, - "texture": 249 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 249, + "id": 12, "interval": 30, - "key": 12, - "repeat": 0, - "texture": 249 + "repeat": 0 }, "32": { "count": 2, + "first_tile": 250, + "id": 32, "interval": 16, - "key": 32, - "repeat": 1, - "texture": 250 + "repeat": 1 }, "45": { "count": 2, + "first_tile": 252, + "id": 45, "interval": 16, - "key": 45, - "repeat": 1, - "texture": 252 + "repeat": 1 }, "46": { "count": 2, + "first_tile": 254, + "id": 46, "interval": 16, - "key": 46, - "repeat": 1, - "texture": 254 + "repeat": 1 } }, "id": 410, @@ -10944,45 +10944,45 @@ "animations": { "0": { "count": 1, + "first_tile": 101, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 101 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 99, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 99 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 100, + "id": 2, "interval": 1, - "key": 2, - "repeat": 0, - "texture": 100 + "repeat": 0 }, "3": { "count": 4, + "first_tile": 103, + "id": 3, "interval": 3, - "key": 3, - "repeat": 0, - "texture": 103 + "repeat": 0 }, "41": { "count": 5, + "first_tile": 102, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 102 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 102, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 102 + "repeat": 0 } }, "id": 565, @@ -11357,52 +11357,52 @@ "animations": { "0": { "count": 1, + "first_tile": 148, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "11": { "count": 4, + "first_tile": 154, + "id": 11, "interval": 4, - "key": 11, - "repeat": 1, - "texture": 154 + "repeat": 1 }, "2": { "count": 6, + "first_tile": 148, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 148 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 144, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "34": { "count": 1, + "first_tile": 148, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 148 + "repeat": 0 }, "5": { "count": 3, + "first_tile": 145, + "id": 5, "interval": 6, - "key": 5, - "repeat": 1, - "texture": 145 + "repeat": 1 }, "6": { "count": 3, + "first_tile": 145, + "id": 6, "interval": 3, - "key": 6, - "repeat": 1, - "texture": 145 + "repeat": 1 } }, "id": 267, @@ -11412,24 +11412,24 @@ "animations": { "13": { "count": 1, + "first_tile": 4, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 4 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 5, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 5 + "repeat": 1 }, "32": { "count": 5, + "first_tile": 5, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 5 + "repeat": 1 } }, "id": 271, @@ -11439,31 +11439,31 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "19": { "count": 7, + "first_tile": 40, + "id": 19, "interval": 2, - "key": 19, - "repeat": 1, - "texture": 40 + "repeat": 1 }, "2": { "count": 7, + "first_tile": 33, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 53, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 53 + "repeat": 0 } }, "id": 280, @@ -11473,45 +11473,45 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "19": { "count": 8, + "first_tile": 48, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "3": { "count": 4, + "first_tile": 2, + "id": 3, "interval": 6, - "key": 3, - "repeat": 0, - "texture": 2 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 32, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "45": { "count": 2, + "first_tile": 0, + "id": 45, "interval": 20, - "key": 45, - "repeat": 1, - "texture": 0 + "repeat": 1 }, "46": { "count": 1, + "first_tile": 1, + "id": 46, "interval": 1, - "key": 46, - "repeat": 0, - "texture": 1 + "repeat": 0 } }, "id": 253, @@ -11521,17 +11521,17 @@ "animations": { "19": { "count": 8, + "first_tile": 56, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 33, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 33 + "repeat": 0 } }, "id": 259, @@ -11556,24 +11556,24 @@ "animations": { "14": { "count": 1, + "first_tile": 6, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 6 + "repeat": 0 }, "41": { "count": 6, + "first_tile": 22, + "id": 41, "interval": 2, - "key": 41, - "repeat": 1, - "texture": 22 + "repeat": 1 }, "9": { "count": 6, + "first_tile": 6, + "id": 9, "interval": 4, - "key": 9, - "repeat": 0, - "texture": 6 + "repeat": 0 } }, "id": 224, @@ -11583,31 +11583,31 @@ "animations": { "0": { "count": 1, + "first_tile": 201, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 201 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 223, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 223 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 202, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 202 + "repeat": 1 }, "41": { "count": 6, + "first_tile": 217, + "id": 41, "interval": 2, - "key": 41, - "repeat": 1, - "texture": 217 + "repeat": 1 } }, "id": 278, @@ -11617,115 +11617,115 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 159, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 159 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 144, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 141, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 141, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 137, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 137 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 138, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 138 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 139, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 140, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 140 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 129, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 149, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 149 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 149, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 149 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 129, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 149, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 149 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 122, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 122, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 122 + "repeat": 1 } }, "id": 306, @@ -11735,17 +11735,17 @@ "animations": { "0": { "count": 5, + "first_tile": 176, + "id": 0, "interval": 7, - "key": 0, - "repeat": 2, - "texture": 176 + "repeat": 2 }, "32": { "count": 8, + "first_tile": 181, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 181 + "repeat": 1 } }, "id": 251, @@ -11755,136 +11755,136 @@ "animations": { "0": { "count": 1, + "first_tile": 80, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 107, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 91, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 91, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 105, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 92, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 92 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 93, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 93 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 94, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 94 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 95, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 95 + "repeat": 0 }, "2": { "count": 10, + "first_tile": 81, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 81 + "repeat": 1 }, "20": { "count": 1, + "first_tile": 64, + "id": 20, "interval": 1, - "key": 20, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "22": { "count": 16, + "first_tile": 64, + "id": 22, "interval": 4, - "key": 22, - "repeat": 1, - "texture": 64 + "repeat": 1 }, "28": { "count": 2, + "first_tile": 105, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 96, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "34": { "count": 1, + "first_tile": 106, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "42": { "count": 5, + "first_tile": 165, + "id": 42, "interval": 4, - "key": 42, - "repeat": 1, - "texture": 165 + "repeat": 1 }, "43": { "count": 5, + "first_tile": 160, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "45": { "count": 1, + "first_tile": 104, + "id": 45, "interval": 1, - "key": 45, - "repeat": 0, - "texture": 104 + "repeat": 0 }, "46": { "count": 2, + "first_tile": 104, + "id": 46, "interval": 8, - "key": 46, - "repeat": 1, - "texture": 104 + "repeat": 1 } }, "id": 225, @@ -11894,73 +11894,73 @@ "animations": { "0": { "count": 6, + "first_tile": 0, + "id": 0, "interval": 8, - "key": 0, - "repeat": 1, - "texture": 0 + "repeat": 1 }, "10": { "count": 4, + "first_tile": 8, + "id": 10, "interval": 4, - "key": 10, - "repeat": 0, - "texture": 8 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 14, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 14 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 16, + "id": 19, "interval": 3, - "key": 19, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "2": { "count": 6, + "first_tile": 24, + "id": 2, "interval": 7, - "key": 2, - "repeat": 1, - "texture": 24 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 13, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "27": { "count": 2, + "first_tile": 8, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 8 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 12, + "id": 3, "interval": 4, - "key": 3, - "repeat": 1, - "texture": 12 + "repeat": 1 }, "45": { "count": 2, + "first_tile": 6, + "id": 45, "interval": 8, - "key": 45, - "repeat": 1, - "texture": 6 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 12, + "id": 5, "interval": 4, - "key": 5, - "repeat": 1, - "texture": 12 + "repeat": 1 } }, "id": 232, @@ -11970,136 +11970,136 @@ "animations": { "0": { "count": 1, + "first_tile": 80, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 107, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 91, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 91, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 105, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 92, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 92 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 93, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 93 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 94, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 94 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 95, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 95 + "repeat": 0 }, "2": { "count": 10, + "first_tile": 81, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 81 + "repeat": 1 }, "20": { "count": 1, + "first_tile": 64, + "id": 20, "interval": 1, - "key": 20, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "22": { "count": 16, + "first_tile": 64, + "id": 22, "interval": 4, - "key": 22, - "repeat": 1, - "texture": 64 + "repeat": 1 }, "28": { "count": 2, + "first_tile": 105, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 96, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "34": { "count": 1, + "first_tile": 106, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "42": { "count": 5, + "first_tile": 165, + "id": 42, "interval": 4, - "key": 42, - "repeat": 1, - "texture": 165 + "repeat": 1 }, "43": { "count": 5, + "first_tile": 160, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "45": { "count": 1, + "first_tile": 104, + "id": 45, "interval": 1, - "key": 45, - "repeat": 0, - "texture": 104 + "repeat": 0 }, "46": { "count": 2, + "first_tile": 104, + "id": 46, "interval": 8, - "key": 46, - "repeat": 1, - "texture": 104 + "repeat": 1 } }, "id": 226, @@ -12109,31 +12109,31 @@ "animations": { "0": { "count": 1, + "first_tile": 162, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 162 + "repeat": 0 }, "19": { "count": 6, + "first_tile": 176, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 176 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 160, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "45": { "count": 6, + "first_tile": 182, + "id": 45, "interval": 6, - "key": 45, - "repeat": 0, - "texture": 182 + "repeat": 0 } }, "id": 248, @@ -12143,59 +12143,59 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 1, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 8, + "id": 2, "interval": 8, - "key": 2, - "repeat": 1, - "texture": 8 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 5, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 5 + "repeat": 0 }, "38": { "count": 2, + "first_tile": 19, + "id": 38, "interval": 1, - "key": 38, - "repeat": 0, - "texture": 19 + "repeat": 0 }, "39": { "count": -3, + "first_tile": 20, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 20 + "repeat": 0 }, "40": { "count": 2, + "first_tile": 16, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 8, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 8 + "repeat": 0 } }, "id": 311, @@ -12205,10 +12205,10 @@ "animations": { "2": { "count": 3, + "first_tile": 189, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 189 + "repeat": 1 } }, "id": 335, @@ -12218,17 +12218,17 @@ "animations": { "0": { "count": 1, + "first_tile": 119, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 119 + "repeat": 0 }, "41": { "count": 5, + "first_tile": 116, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 116 + "repeat": 1 } }, "id": 332, @@ -12238,17 +12238,17 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 0, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 0 + "repeat": 1 } }, "id": 336, @@ -12258,10 +12258,10 @@ "animations": { "2": { "count": 4, + "first_tile": 65, + "id": 2, "interval": 7, - "key": 2, - "repeat": 1, - "texture": 65 + "repeat": 1 } }, "id": 340, @@ -12271,24 +12271,24 @@ "animations": { "2": { "count": 4, + "first_tile": 40, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 40 + "repeat": 1 }, "28": { "count": 4, + "first_tile": 36, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 44, + "id": 5, "interval": 6, - "key": 5, - "repeat": 1, - "texture": 44 + "repeat": 1 } }, "id": 331, @@ -12298,17 +12298,17 @@ "animations": { "0": { "count": 1, + "first_tile": 53, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 53 + "repeat": 0 }, "41": { "count": 5, + "first_tile": 48, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 48 + "repeat": 1 } }, "id": 339, @@ -12318,31 +12318,31 @@ "animations": { "0": { "count": 1, + "first_tile": 117, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 117 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 121, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "2": { "count": 4, + "first_tile": 117, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 117 + "repeat": 1 }, "5": { "count": 7, + "first_tile": 121, + "id": 5, "interval": 4, - "key": 5, - "repeat": 1, - "texture": 121 + "repeat": 1 } }, "id": 334, @@ -12352,17 +12352,17 @@ "animations": { "0": { "count": 1, + "first_tile": 233, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 233 + "repeat": 0 }, "41": { "count": 6, + "first_tile": 234, + "id": 41, "interval": 2, - "key": 41, - "repeat": 1, - "texture": 234 + "repeat": 1 } }, "id": 337, @@ -12372,38 +12372,38 @@ "animations": { "0": { "count": 1, + "first_tile": 54, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 54 + "repeat": 0 }, "10": { "count": 1, + "first_tile": 74, + "id": 10, "interval": 1, - "key": 10, - "repeat": 0, - "texture": 74 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 55, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 55 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 70, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 73, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 73 + "repeat": 0 } }, "id": 338, @@ -12413,31 +12413,31 @@ "animations": { "0": { "count": 4, + "first_tile": 80, + "id": 0, "interval": 5, - "key": 0, - "repeat": 1, - "texture": 80 + "repeat": 1 }, "2": { "count": 5, + "first_tile": 84, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 84 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 89, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 89 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 89, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 89 + "repeat": 0 } }, "id": 341, @@ -12447,17 +12447,17 @@ "animations": { "0": { "count": 1, + "first_tile": 63, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 63 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 26, + "id": 2, "interval": 7, - "key": 2, - "repeat": 1, - "texture": 26 + "repeat": 1 } }, "id": 333, @@ -12467,73 +12467,73 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 137, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 137 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 137, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 137 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 138, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 138 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 139, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 140, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 140 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 141, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 144, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 129, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 129, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 129 + "repeat": 1 } }, "id": 247, @@ -12543,52 +12543,52 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "10": { "count": 6, + "first_tile": 10, + "id": 10, "interval": 6, - "key": 10, - "repeat": 1, - "texture": 10 + "repeat": 1 }, "2": { "count": 7, + "first_tile": 1, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 13, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "27": { "count": 3, + "first_tile": 8, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 8 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 10, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 9, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 9 + "repeat": 0 } }, "id": 290, @@ -12598,45 +12598,45 @@ "animations": { "0": { "count": 5, + "first_tile": 96, + "id": 0, "interval": 8, - "key": 0, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "2": { "count": 5, + "first_tile": 248, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 248 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 101, + "id": 27, "interval": 6, - "key": 27, - "repeat": 0, - "texture": 101 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 102, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 102 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 106, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "45": { "count": 5, + "first_tile": 112, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 112 + "repeat": 0 } }, "id": 261, @@ -12646,31 +12646,31 @@ "animations": { "19": { "count": 5, + "first_tile": 54, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 54 + "repeat": 0 }, "27": { "count": 5, + "first_tile": 58, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 58 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 48, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 48, + "id": 8, "interval": 4, - "key": 8, - "repeat": 1, - "texture": 48 + "repeat": 1 } }, "id": 241, @@ -12680,38 +12680,38 @@ "animations": { "0": { "count": 1, + "first_tile": 241, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 241 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 242, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 242 + "repeat": 1 }, "27": { "count": -3, + "first_tile": 249, + "id": 27, "interval": 5, - "key": 27, - "repeat": 0, - "texture": 249 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 247, + "id": 28, "interval": 5, - "key": 28, - "repeat": 0, - "texture": 247 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 250, + "id": 41, "interval": 3, - "key": 41, - "repeat": 1, - "texture": 250 + "repeat": 1 } }, "id": 242, @@ -12721,59 +12721,59 @@ "animations": { "0": { "count": 4, + "first_tile": 192, + "id": 0, "interval": 6, - "key": 0, - "repeat": 2, - "texture": 192 + "repeat": 2 }, "2": { "count": 7, + "first_tile": 249, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 249 + "repeat": 1 }, "27": { "count": 4, + "first_tile": 219, + "id": 27, "interval": 8, - "key": 27, - "repeat": 0, - "texture": 219 + "repeat": 0 }, "28": { "count": 4, + "first_tile": 215, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 215 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 196, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 196 + "repeat": 0 }, "39": { "count": 1, + "first_tile": 235, + "id": 39, "interval": 1, - "key": 39, - "repeat": 0, - "texture": 235 + "repeat": 0 }, "40": { "count": 4, + "first_tile": 231, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 231 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 196, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 196 + "repeat": 0 } }, "id": 284, @@ -12783,38 +12783,38 @@ "animations": { "0": { "count": 1, + "first_tile": 23, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 23 + "repeat": 0 }, "19": { "count": 7, + "first_tile": 16, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "2": { "count": 7, + "first_tile": 16, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "41": { "count": 7, + "first_tile": 16, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "5": { "count": 6, + "first_tile": 24, + "id": 5, "interval": 4, - "key": 5, - "repeat": 1, - "texture": 24 + "repeat": 1 } }, "id": 262, @@ -12824,59 +12824,59 @@ "animations": { "0": { "count": 4, + "first_tile": 176, + "id": 0, "interval": 6, - "key": 0, - "repeat": 2, - "texture": 176 + "repeat": 2 }, "2": { "count": 7, + "first_tile": 242, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 242 + "repeat": 1 }, "27": { "count": 4, + "first_tile": 187, + "id": 27, "interval": 8, - "key": 27, - "repeat": 0, - "texture": 187 + "repeat": 0 }, "28": { "count": 4, + "first_tile": 183, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 183 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 180, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 180 + "repeat": 0 }, "39": { "count": 1, + "first_tile": 203, + "id": 39, "interval": 1, - "key": 39, - "repeat": 0, - "texture": 203 + "repeat": 0 }, "40": { "count": 4, + "first_tile": 199, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 199 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 180, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 180 + "repeat": 0 } }, "id": 283, @@ -12886,17 +12886,17 @@ "animations": { "22": { "count": 3, + "first_tile": 11, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 7, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 7 + "repeat": 1 } }, "id": 314, @@ -12906,17 +12906,17 @@ "animations": { "22": { "count": 3, + "first_tile": 11, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 7, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 7 + "repeat": 1 } }, "id": 315, @@ -12926,24 +12926,24 @@ "animations": { "12": { "count": 1, + "first_tile": 11, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 8, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 8 + "repeat": 0 }, "41": { "count": 8, + "first_tile": 0, + "id": 41, "interval": 5, - "key": 41, - "repeat": 1, - "texture": 0 + "repeat": 1 } }, "id": 317, @@ -12953,24 +12953,24 @@ "animations": { "12": { "count": 1, + "first_tile": 30, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 30 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 35, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 35 + "repeat": 0 }, "41": { "count": 6, + "first_tile": 24, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 24 + "repeat": 1 } }, "id": 319, @@ -12980,24 +12980,24 @@ "animations": { "12": { "count": 1, + "first_tile": 22, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 22 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 32, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "41": { "count": 6, + "first_tile": 16, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 16 + "repeat": 1 } }, "id": 318, @@ -13007,24 +13007,24 @@ "animations": { "12": { "count": 1, + "first_tile": 31, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 31 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 20, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 20 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 16, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 16 + "repeat": 1 } }, "id": 320, @@ -13034,24 +13034,24 @@ "animations": { "12": { "count": 1, + "first_tile": 47, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 47 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 36, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 32, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 32 + "repeat": 1 } }, "id": 323, @@ -13061,24 +13061,24 @@ "animations": { "12": { "count": 1, + "first_tile": 15, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 15 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 4, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 4 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 0, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 0 + "repeat": 1 } }, "id": 321, @@ -13088,24 +13088,24 @@ "animations": { "12": { "count": 1, + "first_tile": 63, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 63 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 52, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 52 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 48, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 48 + "repeat": 1 } }, "id": 322, @@ -13115,24 +13115,24 @@ "animations": { "2": { "count": 4, + "first_tile": 4, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 4 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 1, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "32": { "count": 4, + "first_tile": 4, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 4 + "repeat": 1 } }, "id": 265, @@ -13142,24 +13142,24 @@ "animations": { "22": { "count": 3, + "first_tile": 48, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "41": { "count": 5, + "first_tile": 40, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 40 + "repeat": 1 }, "45": { "count": 1, + "first_tile": 49, + "id": 45, "interval": 1, - "key": 45, - "repeat": 0, - "texture": 49 + "repeat": 0 } }, "id": 288, @@ -13169,31 +13169,31 @@ "animations": { "0": { "count": 3, + "first_tile": 0, + "id": 0, "interval": 8, - "key": 0, - "repeat": 2, - "texture": 0 + "repeat": 2 }, "13": { "count": 2, + "first_tile": 3, + "id": 13, "interval": 7, - "key": 13, - "repeat": 0, - "texture": 3 + "repeat": 0 }, "3": { "count": 2, + "first_tile": 3, + "id": 3, "interval": 7, - "key": 3, - "repeat": 0, - "texture": 3 + "repeat": 0 }, "9": { "count": -2, + "first_tile": 4, + "id": 9, "interval": 4, - "key": 9, - "repeat": 0, - "texture": 4 + "repeat": 0 } }, "id": 285, @@ -13203,45 +13203,45 @@ "animations": { "0": { "count": 4, + "first_tile": 32, + "id": 0, "interval": 6, - "key": 0, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "14": { "count": 1, + "first_tile": 40, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 40 + "repeat": 0 }, "19": { "count": 6, + "first_tile": 48, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "2": { "count": 4, + "first_tile": 36, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 36 + "repeat": 1 }, "3": { "count": 3, + "first_tile": 44, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 44 + "repeat": 0 }, "5": { "count": 5, + "first_tile": 40, + "id": 5, "interval": 6, - "key": 5, - "repeat": 0, - "texture": 40 + "repeat": 0 } }, "id": 223, @@ -13251,31 +13251,31 @@ "animations": { "0": { "count": 1, + "first_tile": 158, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 158 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 166, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 166 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 159, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 159 + "repeat": 0 }, "9": { "count": 3, + "first_tile": 172, + "id": 9, "interval": 4, - "key": 9, - "repeat": 0, - "texture": 172 + "repeat": 0 } }, "id": 309, @@ -13285,45 +13285,45 @@ "animations": { "0": { "count": 1, + "first_tile": 154, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 154 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 143, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "32": { "count": 5, + "first_tile": 154, + "id": 32, "interval": 8, - "key": 32, - "repeat": 1, - "texture": 154 + "repeat": 1 }, "41": { "count": 5, + "first_tile": 138, + "id": 41, "interval": 8, - "key": 41, - "repeat": 1, - "texture": 138 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 143, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "8": { "count": 1, + "first_tile": 138, + "id": 8, "interval": 1, - "key": 8, - "repeat": 0, - "texture": 138 + "repeat": 0 } }, "id": 286, @@ -13333,52 +13333,52 @@ "animations": { "0": { "count": 1, + "first_tile": 230, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 230 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 230, + "id": 14, "interval": 6, - "key": 14, - "repeat": 1, - "texture": 230 + "repeat": 1 }, "19": { "count": 3, + "first_tile": 237, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 237 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 215, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 215 + "repeat": 1 }, "3": { "count": 3, + "first_tile": 220, + "id": 3, "interval": 2, - "key": 3, - "repeat": 0, - "texture": 220 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 222, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 222 + "repeat": 0 }, "6": { "count": 3, + "first_tile": 234, + "id": 6, "interval": 4, - "key": 6, - "repeat": 0, - "texture": 234 + "repeat": 0 } }, "id": 222, @@ -13388,129 +13388,129 @@ "animations": { "0": { "count": 1, + "first_tile": 40, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 40 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 15, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 15 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 15, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 15 + "repeat": 0 }, "14": { "count": 4, + "first_tile": 107, + "id": 14, "interval": 5, - "key": 14, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 12, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 11, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 14, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 14 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 13, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 69, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 69 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 40, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 40 + "repeat": 1 }, "25": { "count": 2, + "first_tile": 240, + "id": 25, "interval": 5, - "key": 25, - "repeat": 0, - "texture": 240 + "repeat": 0 }, "26": { "count": 2, + "first_tile": 246, + "id": 26, "interval": 5, - "key": 26, - "repeat": 0, - "texture": 246 + "repeat": 0 }, "27": { "count": 6, + "first_tile": 57, + "id": 27, "interval": 6, - "key": 27, - "repeat": 0, - "texture": 57 + "repeat": 0 }, "28": { "count": 6, + "first_tile": 52, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 52 + "repeat": 0 }, "33": { "count": 4, + "first_tile": 242, + "id": 33, "interval": 5, - "key": 33, - "repeat": 0, - "texture": 242 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 224, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "8": { "count": 8, + "first_tile": 225, + "id": 8, "interval": 7, - "key": 8, - "repeat": 1, - "texture": 225 + "repeat": 1 }, "9": { "count": 1, + "first_tile": 52, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 52 + "repeat": 0 } }, "id": 264, @@ -13520,101 +13520,101 @@ "animations": { "0": { "count": 1, + "first_tile": 105, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 121, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 121, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 121, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 121, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 121, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 121, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 121, + "id": 19, "interval": 3, - "key": 19, - "repeat": 1, - "texture": 121 + "repeat": 1 }, "2": { "count": 7, + "first_tile": 105, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 105 + "repeat": 1 }, "27": { "count": 4, + "first_tile": 204, + "id": 27, "interval": 8, - "key": 27, - "repeat": 0, - "texture": 204 + "repeat": 0 }, "28": { "count": 4, + "first_tile": 200, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 200 + "repeat": 0 }, "3": { "count": 2, + "first_tile": 125, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 125 + "repeat": 0 }, "32": { "count": 7, + "first_tile": 105, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 105 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 126, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 126 + "repeat": 0 } }, "id": 230, @@ -13629,115 +13629,115 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 9, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 64, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 73, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 73 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 73, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 73 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 69, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 69 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 70, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 70 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 71, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 71 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 72, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 72 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 160, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 160, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 160 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 1, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 160, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 160 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 112, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 112, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 112 + "repeat": 1 } }, "id": 307, @@ -13757,17 +13757,17 @@ "animations": { "34": { "count": 6, + "first_tile": 4, + "id": 34, "interval": 4, - "key": 34, - "repeat": 1, - "texture": 4 + "repeat": 1 }, "41": { "count": 6, + "first_tile": 20, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 20 + "repeat": 1 } }, "id": 243, @@ -13777,38 +13777,38 @@ "animations": { "0": { "count": 5, + "first_tile": 0, + "id": 0, "interval": 8, - "key": 0, - "repeat": 1, - "texture": 0 + "repeat": 1 }, "2": { "count": 4, + "first_tile": 220, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 220 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 5, + "id": 27, "interval": 6, - "key": 27, - "repeat": 0, - "texture": 5 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 6, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 6 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 10, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 10 + "repeat": 0 } }, "id": 260, @@ -13818,17 +13818,17 @@ "animations": { "0": { "count": 1, + "first_tile": 96, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 97, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 97 + "repeat": 1 } }, "id": 289, @@ -13843,31 +13843,31 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 8, + "id": 2, "interval": 8, - "key": 2, - "repeat": 1, - "texture": 8 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 13, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "41": { "count": 7, + "first_tile": 1, + "id": 41, "interval": 5, - "key": 41, - "repeat": 1, - "texture": 1 + "repeat": 1 } }, "id": 274, @@ -13877,80 +13877,80 @@ "animations": { "0": { "count": 1, + "first_tile": 24, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 24 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 37, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 37 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 28, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 28 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 24, + "id": 2, "interval": 1, - "key": 2, - "repeat": 0, - "texture": 24 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 21, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 21 + "repeat": 0 }, "3": { "count": 2, + "first_tile": 38, + "id": 3, "interval": 10, - "key": 3, - "repeat": 0, - "texture": 38 + "repeat": 0 }, "31": { "count": 3, + "first_tile": 25, + "id": 31, "interval": 8, - "key": 31, - "repeat": 0, - "texture": 25 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 24, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 24 + "repeat": 0 }, "45": { "count": 6, + "first_tile": 32, + "id": 45, "interval": 5, - "key": 45, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "46": { "count": -6, + "first_tile": 37, + "id": 46, "interval": 5, - "key": 46, - "repeat": 0, - "texture": 37 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 38, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 38 + "repeat": 0 } }, "id": 244, @@ -13960,73 +13960,73 @@ "animations": { "0": { "count": 1, + "first_tile": 208, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 208 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 47, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 47 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 47, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 47 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 60, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 60 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 61, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 61 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 62, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 62 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 63, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 63 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 28, + "id": 19, "interval": 4, - "key": 19, - "repeat": 2, - "texture": 28 + "repeat": 2 }, "2": { "count": 8, + "first_tile": 209, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 209 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 209, + "id": 32, "interval": 4, - "key": 32, - "repeat": 1, - "texture": 209 + "repeat": 1 } }, "id": 310, @@ -14036,24 +14036,24 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 33, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 24, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 24 + "repeat": 0 } }, "id": 305, @@ -14063,52 +14063,52 @@ "animations": { "0": { "count": 4, + "first_tile": 228, + "id": 0, "interval": 6, - "key": 0, - "repeat": 1, - "texture": 228 + "repeat": 1 }, "13": { "count": 5, + "first_tile": 232, + "id": 13, "interval": 6, - "key": 13, - "repeat": 0, - "texture": 232 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 240, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 240 + "repeat": 1 }, "27": { "count": 3, + "first_tile": 232, + "id": 27, "interval": 6, - "key": 27, - "repeat": 0, - "texture": 232 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 225, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 225 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 224, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 224, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 224 + "repeat": 0 } }, "id": 239, @@ -14118,59 +14118,59 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 143, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 143, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 143, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 143, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 143, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 143 + "repeat": 0 }, "19": { "count": 7, + "first_tile": 136, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 136 + "repeat": 1 }, "2": { "count": 8, + "first_tile": 128, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 128 + "repeat": 1 } }, "id": 233, @@ -14180,59 +14180,59 @@ "animations": { "0": { "count": 1, + "first_tile": 210, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 210 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 223, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 223 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 223, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 223 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 219, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 219 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 220, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 220 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 221, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 221 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 222, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 222 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 211, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 211 + "repeat": 1 } }, "id": 299, @@ -14252,115 +14252,115 @@ "animations": { "0": { "count": 1, + "first_tile": 224, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 255, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 255 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 240, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 240 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 237, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 237 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 237, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 237 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 233, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 233 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 234, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 234 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 235, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 235 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 236, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 236 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 225, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 225 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 245, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 245 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 245, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 245 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 225, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 225 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 245, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 245 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 218, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 218 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 218, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 218 + "repeat": 1 } }, "id": 297, @@ -14370,101 +14370,101 @@ "animations": { "0": { "count": 1, + "first_tile": 64, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 77, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 77 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 77, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 77 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 73, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 73 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 74, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 74 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 75, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 75 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 76, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 76 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 65, + "id": 2, "interval": 3, - "key": 2, - "repeat": 1, - "texture": 65 + "repeat": 1 }, "27": { "count": 4, + "first_tile": 101, + "id": 27, "interval": 3, - "key": 27, - "repeat": 0, - "texture": 101 + "repeat": 0 }, "28": { "count": 4, + "first_tile": 91, + "id": 28, "interval": 3, - "key": 28, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "29": { "count": 4, + "first_tile": 87, + "id": 29, "interval": 3, - "key": 29, - "repeat": 1, - "texture": 87 + "repeat": 1 }, "3": { "count": 3, + "first_tile": 80, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "30": { "count": 4, + "first_tile": 83, + "id": 30, "interval": 3, - "key": 30, - "repeat": 1, - "texture": 83 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 65, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 65 + "repeat": 1 } }, "id": 231, @@ -14474,31 +14474,31 @@ "animations": { "0": { "count": 1, + "first_tile": 208, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 208 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 211, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 211 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 209, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 209 + "repeat": 0 }, "8": { "count": 1, + "first_tile": 210, + "id": 8, "interval": 1, - "key": 8, - "repeat": 0, - "texture": 210 + "repeat": 0 } }, "id": 238, @@ -14508,17 +14508,17 @@ "animations": { "19": { "count": 1, + "first_tile": 240, + "id": 19, "interval": 1, - "key": 19, - "repeat": 0, - "texture": 240 + "repeat": 0 }, "41": { "count": 6, + "first_tile": 224, + "id": 41, "interval": 2, - "key": 41, - "repeat": 1, - "texture": 224 + "repeat": 1 } }, "id": 237, @@ -14528,31 +14528,31 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "19": { "count": 12, + "first_tile": 19, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 19 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 8, + "id": 2, "interval": 8, - "key": 2, - "repeat": 1, - "texture": 8 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 16, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 16 + "repeat": 0 } }, "id": 249, @@ -14562,80 +14562,80 @@ "animations": { "0": { "count": 1, + "first_tile": 192, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 192 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 205, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 205 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 205, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 205 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 201, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 201 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 202, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 202 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 203, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 203 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 204, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 204 + "repeat": 0 }, "19": { "count": 2, + "first_tile": 212, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 212 + "repeat": 0 }, "2": { "count": 9, + "first_tile": 192, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 192 + "repeat": 1 }, "45": { "count": 2, + "first_tile": 208, + "id": 45, "interval": 6, - "key": 45, - "repeat": 0, - "texture": 208 + "repeat": 0 }, "46": { "count": 2, + "first_tile": 210, + "id": 46, "interval": 6, - "key": 46, - "repeat": 1, - "texture": 210 + "repeat": 1 } }, "id": 252, @@ -14645,80 +14645,80 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 68, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 68 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 68, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 68 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 64, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 65, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 65 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 66, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 66 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 67, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 67 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 80, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 32, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "3": { "count": 4, + "first_tile": 48, + "id": 3, "interval": 2, - "key": 3, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 32, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 32 + "repeat": 1 } }, "id": 263, @@ -14728,115 +14728,115 @@ "animations": { "0": { "count": 1, + "first_tile": 176, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 176 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 207, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 207 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 192, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 192 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 189, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 189 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 189, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 189 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 185, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 185 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 186, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 186 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 187, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 187 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 188, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 188 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 177, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 177 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 197, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 197 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 197, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 197 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 177, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 177 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 197, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 197 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 170, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 170 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 170, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 170 + "repeat": 1 } }, "id": 303, @@ -14846,87 +14846,87 @@ "animations": { "0": { "count": 1, + "first_tile": 112, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 126, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 126, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 122, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 123, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 123 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 124, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 125, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 125 + "repeat": 0 }, "19": { "count": 1, + "first_tile": 121, + "id": 19, "interval": 1, - "key": 19, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 113, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "3": { "count": 2, + "first_tile": 119, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 119 + "repeat": 0 }, "32": { "count": 6, + "first_tile": 113, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "34": { "count": 1, + "first_tile": 112, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 112 + "repeat": 0 } }, "id": 276, @@ -14936,87 +14936,87 @@ "animations": { "0": { "count": 1, + "first_tile": 112, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 126, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 126, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 122, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 123, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 123 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 124, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 125, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 125 + "repeat": 0 }, "19": { "count": 1, + "first_tile": 121, + "id": 19, "interval": 1, - "key": 19, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 113, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "3": { "count": 2, + "first_tile": 119, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 119 + "repeat": 0 }, "32": { "count": 6, + "first_tile": 113, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "34": { "count": 1, + "first_tile": 112, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 112 + "repeat": 0 } }, "id": 275, @@ -15026,87 +15026,87 @@ "animations": { "0": { "count": 1, + "first_tile": 112, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 126, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 126, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 126 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 122, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 123, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 123 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 124, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 124 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 125, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 125 + "repeat": 0 }, "19": { "count": 1, + "first_tile": 121, + "id": 19, "interval": 1, - "key": 19, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 113, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "3": { "count": 2, + "first_tile": 119, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 119 + "repeat": 0 }, "32": { "count": 6, + "first_tile": 113, + "id": 32, "interval": 2, - "key": 32, - "repeat": 1, - "texture": 113 + "repeat": 1 }, "34": { "count": 1, + "first_tile": 112, + "id": 34, "interval": 1, - "key": 34, - "repeat": 0, - "texture": 112 + "repeat": 0 } }, "id": 277, @@ -15116,17 +15116,17 @@ "animations": { "19": { "count": 4, + "first_tile": 0, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 0, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "id": 258, @@ -15136,24 +15136,24 @@ "animations": { "12": { "count": 1, + "first_tile": 1, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 2, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 2 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 0, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 0 + "repeat": 0 } }, "id": 257, @@ -15163,108 +15163,108 @@ "animations": { "0": { "count": 1, + "first_tile": 48, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "11": { "count": 12, + "first_tile": 84, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 84 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 57, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 57 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 57, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 57 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 60, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 60 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 61, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 61 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 62, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 62 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 63, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 63 + "repeat": 0 }, "19": { "count": 12, + "first_tile": 72, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 72 + "repeat": 1 }, "2": { "count": 8, + "first_tile": 49, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 49 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 64, + "id": 23, "interval": 4, - "key": 23, - "repeat": 1, - "texture": 64 + "repeat": 1 }, "3": { "count": 5, + "first_tile": 49, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 49 + "repeat": 0 }, "43": { "count": 2, + "first_tile": 58, + "id": 43, "interval": 4, - "key": 43, - "repeat": 0, - "texture": 58 + "repeat": 0 }, "44": { "count": -2, + "first_tile": 59, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 59 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 53, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 53 + "repeat": 0 } }, "id": 327, @@ -15274,108 +15274,108 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "11": { "count": 12, + "first_tile": 36, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 12, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 13, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 14, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 14 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 15, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 15 + "repeat": 0 }, "19": { "count": 12, + "first_tile": 24, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 24 + "repeat": 1 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 16, + "id": 23, "interval": 4, - "key": 23, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "3": { "count": 5, + "first_tile": 1, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "43": { "count": 2, + "first_tile": 10, + "id": 43, "interval": 4, - "key": 43, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "44": { "count": -2, + "first_tile": 11, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 5, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 5 + "repeat": 0 } }, "id": 326, @@ -15385,108 +15385,108 @@ "animations": { "0": { "count": 1, + "first_tile": 96, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "11": { "count": 12, + "first_tile": 132, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 132 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 105, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 105, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 108, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 108 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 109, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 109 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 110, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 110 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 111, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 111 + "repeat": 0 }, "19": { "count": 12, + "first_tile": 120, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 120 + "repeat": 1 }, "2": { "count": 8, + "first_tile": 97, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 97 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 112, + "id": 23, "interval": 4, - "key": 23, - "repeat": 1, - "texture": 112 + "repeat": 1 }, "3": { "count": 5, + "first_tile": 97, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 97 + "repeat": 0 }, "43": { "count": 2, + "first_tile": 106, + "id": 43, "interval": 4, - "key": 43, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "44": { "count": -2, + "first_tile": 107, + "id": 44, "interval": 4, - "key": 44, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 101, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 101 + "repeat": 0 } }, "id": 328, @@ -15496,87 +15496,87 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 12, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 13, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 14, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 14 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 15, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 15 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 16, + "id": 23, "interval": 4, - "key": 23, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "3": { "count": 5, + "first_tile": 1, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 1 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 5, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 5 + "repeat": 0 } }, "id": 219, @@ -15586,66 +15586,66 @@ "animations": { "0": { "count": 5, + "first_tile": 32, + "id": 0, "interval": 4, - "key": 0, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "10": { "count": 5, + "first_tile": 21, + "id": 10, "interval": 4, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 47, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 47 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 43, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 44, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 44 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 45, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 45 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 46, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 46 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 37, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 37 + "repeat": 1 }, "45": { "count": 3, + "first_tile": 26, + "id": 45, "interval": 5, - "key": 45, - "repeat": 1, - "texture": 26 + "repeat": 1 } }, "id": 272, @@ -15655,10 +15655,10 @@ "animations": { "41": { "count": 6, + "first_tile": 56, + "id": 41, "interval": 2, - "key": 41, - "repeat": 1, - "texture": 56 + "repeat": 1 } }, "id": 279, @@ -15668,31 +15668,31 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "2": { "count": 9, + "first_tile": 37, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 37 + "repeat": 1 }, "3": { "count": 4, + "first_tile": 33, + "id": 3, "interval": 8, - "key": 3, - "repeat": 0, - "texture": 33 + "repeat": 0 }, "5": { "count": -4, + "first_tile": 36, + "id": 5, "interval": 8, - "key": 5, - "repeat": 0, - "texture": 36 + "repeat": 0 } }, "id": 228, @@ -15702,38 +15702,38 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 16, + "id": 19, "interval": 4, - "key": 19, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "2": { "count": 4, + "first_tile": 0, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 0 + "repeat": 1 }, "22": { "count": 4, + "first_tile": 32, + "id": 22, "interval": 4, - "key": 22, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "32": { "count": 4, + "first_tile": 0, + "id": 32, "interval": 4, - "key": 32, - "repeat": 1, - "texture": 0 + "repeat": 1 } }, "id": 240, @@ -15743,10 +15743,10 @@ "animations": { "2": { "count": 4, + "first_tile": 92, + "id": 2, "interval": 2, - "key": 2, - "repeat": 1, - "texture": 92 + "repeat": 1 } }, "id": 295, @@ -15756,38 +15756,38 @@ "animations": { "0": { "count": 5, + "first_tile": 192, + "id": 0, "interval": 6, - "key": 0, - "repeat": 1, - "texture": 192 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 213, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 213 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 197, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 197 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 208, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 208 + "repeat": 1 }, "3": { "count": 4, + "first_tile": 197, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 197 + "repeat": 0 } }, "id": 229, @@ -15797,115 +15797,115 @@ "animations": { "0": { "count": 1, + "first_tile": 96, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 127, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 127 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 112, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 109, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 109 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 109, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 109 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 105, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 106, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 107, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 108, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 108 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 97, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 97 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 117, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 117 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 117, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 117 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 97, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 97 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 117, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 117 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 90, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 90 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 90, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 90 + "repeat": 1 } }, "id": 296, @@ -15915,108 +15915,108 @@ "animations": { "0": { "count": 1, + "first_tile": 96, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 112, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 109, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 109 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 109, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 109 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 105, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 106, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 107, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 107 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 108, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 108 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 97, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 97 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 117, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 117 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 117, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 117 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 97, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 97 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 117, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 117 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 90, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 90 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 90, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 90 + "repeat": 1 } }, "id": 273, @@ -16026,115 +16026,115 @@ "animations": { "0": { "count": 1, + "first_tile": 80, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 111, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 111 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 96, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 93, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 93 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 93, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 93 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 89, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 89 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 90, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 90 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 91, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 91 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 92, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 92 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 81, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 81 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 101, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 101 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 101, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 101 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 81, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 81 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 101, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 101 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 74, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 74 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 74, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 74 + "repeat": 1 } }, "id": 302, @@ -16144,115 +16144,115 @@ "animations": { "0": { "count": 1, + "first_tile": 176, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 176 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 207, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 207 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 192, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 192 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 189, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 189 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 189, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 189 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 185, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 185 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 186, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 186 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 187, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 187 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 188, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 188 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 177, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 177 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 197, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 197 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 197, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 197 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 177, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 177 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 197, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 197 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 170, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 170 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 170, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 170 + "repeat": 1 } }, "id": 300, @@ -16262,115 +16262,115 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 159, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 159 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 144, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 141, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 141, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 137, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 137 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 138, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 138 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 139, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 140, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 140 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 129, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 149, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 149 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 149, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 149 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 129, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 149, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 149 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 122, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 122, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 122 + "repeat": 1 } }, "id": 301, @@ -16380,31 +16380,31 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "2": { "count": 9, + "first_tile": 37, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 37 + "repeat": 1 }, "3": { "count": 4, + "first_tile": 33, + "id": 3, "interval": 8, - "key": 3, - "repeat": 0, - "texture": 33 + "repeat": 0 }, "5": { "count": -4, + "first_tile": 36, + "id": 5, "interval": 8, - "key": 5, - "repeat": 0, - "texture": 36 + "repeat": 0 } }, "id": 227, @@ -16414,24 +16414,24 @@ "animations": { "0": { "count": 1, + "first_tile": 2, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 2 + "repeat": 0 }, "19": { "count": 6, + "first_tile": 16, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 0, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 0 + "repeat": 1 } }, "id": 220, @@ -16441,80 +16441,80 @@ "animations": { "0": { "count": 1, + "first_tile": 149, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 149 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 173, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 173 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 173, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 173 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 158, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 158 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 159, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 159 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 174, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 174 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 175, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 175 + "repeat": 0 }, "19": { "count": 7, + "first_tile": 166, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 166 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 150, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 150 + "repeat": 1 }, "3": { "count": 5, + "first_tile": 160, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 160 + "repeat": 0 }, "41": { "count": 1, + "first_tile": 165, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 165 + "repeat": 0 } }, "id": 250, @@ -16524,38 +16524,38 @@ "animations": { "0": { "count": 1, + "first_tile": 48, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 56, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 56 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 48, + "id": 2, "interval": 6, - "key": 2, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "3": { "count": 3, + "first_tile": 53, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 53 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 57, + "id": 5, "interval": 8, - "key": 5, - "repeat": 0, - "texture": 57 + "repeat": 0 } }, "id": 221, @@ -16565,38 +16565,38 @@ "animations": { "0": { "count": 1, + "first_tile": 8, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 8 + "repeat": 0 }, "11": { "count": 1, + "first_tile": 9, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "2": { "count": 1, + "first_tile": 9, + "id": 2, "interval": 1, - "key": 2, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "22": { "count": 3, + "first_tile": 4, + "id": 22, "interval": 5, - "key": 22, - "repeat": 0, - "texture": 4 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 9, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 9 + "repeat": 0 } }, "id": 308, @@ -16606,31 +16606,31 @@ "animations": { "0": { "count": 1, + "first_tile": 208, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 208 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 105, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 105 + "repeat": 0 }, "2": { "count": 5, + "first_tile": 209, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 209 + "repeat": 1 }, "5": { "count": 6, + "first_tile": 106, + "id": 5, "interval": 4, - "key": 5, - "repeat": 1, - "texture": 106 + "repeat": 1 } }, "id": 287, @@ -16640,115 +16640,115 @@ "animations": { "0": { "count": 1, + "first_tile": 16, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 47, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 47 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 32, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 29, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 29 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 29, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 29 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 25, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 25 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 26, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 26 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 27, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 27 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 28, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 28 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 17, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 17 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 37, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 37 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 37, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 37 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 17, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 17 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 37, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 37 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 10, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 10, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 10 + "repeat": 1 } }, "id": 304, @@ -16763,80 +16763,80 @@ "animations": { "0": { "count": 1, + "first_tile": 144, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 160, + "id": 11, "interval": 4, - "key": 11, - "repeat": 0, - "texture": 160 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 153, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 153 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 153, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 153 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 154, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 154 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 155, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 155 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 156, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 156 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 157, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 157 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 145, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 145 + "repeat": 1 }, "32": { "count": 8, + "first_tile": 145, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 145 + "repeat": 1 }, "43": { "count": 5, + "first_tile": 10, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 10 + "repeat": 1 } }, "id": 234, @@ -16846,31 +16846,31 @@ "animations": { "13": { "count": 1, + "first_tile": 141, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 136, + "id": 19, "interval": 6, - "key": 19, - "repeat": 0, - "texture": 136 + "repeat": 0 }, "41": { "count": 8, + "first_tile": 128, + "id": 41, "interval": 6, - "key": 41, - "repeat": 1, - "texture": 128 + "repeat": 1 }, "5": { "count": 8, + "first_tile": 128, + "id": 5, "interval": 6, - "key": 5, - "repeat": 1, - "texture": 128 + "repeat": 1 } }, "id": 266, @@ -16880,101 +16880,101 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 9, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 9, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 22, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 22 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 10, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 11, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 13, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 12, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 14, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 14 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "41": { "count": 6, + "first_tile": 16, + "id": 41, "interval": 3, - "key": 41, - "repeat": 1, - "texture": 16 + "repeat": 1 }, "5": { "count": 8, + "first_tile": 1, + "id": 5, "interval": 3, - "key": 5, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "9": { "count": 6, + "first_tile": 22, + "id": 9, "interval": 4, - "key": 9, - "repeat": 0, - "texture": 22 + "repeat": 0 } }, "id": 245, @@ -16984,101 +16984,101 @@ "animations": { "0": { "count": 1, + "first_tile": 32, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 41, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 41 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 41, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 41 + "repeat": 0 }, "14": { "count": 1, + "first_tile": 54, + "id": 14, "interval": 1, - "key": 14, - "repeat": 0, - "texture": 54 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 42, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 42 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 43, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 43 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 45, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 45 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 44, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 44 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 33, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 46, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 46 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 33, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "41": { "count": 6, + "first_tile": 48, + "id": 41, "interval": 3, - "key": 41, - "repeat": 1, - "texture": 48 + "repeat": 1 }, "5": { "count": 8, + "first_tile": 33, + "id": 5, "interval": 3, - "key": 5, - "repeat": 1, - "texture": 33 + "repeat": 1 }, "9": { "count": 6, + "first_tile": 54, + "id": 9, "interval": 4, - "key": 9, - "repeat": 0, - "texture": 54 + "repeat": 0 } }, "id": 246, @@ -17088,87 +17088,87 @@ "animations": { "0": { "count": 1, + "first_tile": 176, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 176 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 185, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 185 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 185, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 185 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 186, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 186 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 187, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 187 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 188, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 188 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 189, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 189 + "repeat": 0 }, "19": { "count": 3, + "first_tile": 169, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 169 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 177, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 177 + "repeat": 1 }, "43": { "count": 5, + "first_tile": 96, + "id": 43, "interval": 4, - "key": 43, - "repeat": 1, - "texture": 96 + "repeat": 1 }, "45": { "count": 1, + "first_tile": 165, + "id": 45, "interval": 40, - "key": 45, - "repeat": 0, - "texture": 165 + "repeat": 0 }, "46": { "count": 3, + "first_tile": 166, + "id": 46, "interval": 6, - "key": 46, - "repeat": 1, - "texture": 166 + "repeat": 1 } }, "id": 235, @@ -17178,17 +17178,17 @@ "animations": { "22": { "count": 4, + "first_tile": 196, + "id": 22, "interval": 8, - "key": 22, - "repeat": 0, - "texture": 196 + "repeat": 0 }, "41": { "count": 4, + "first_tile": 192, + "id": 41, "interval": 8, - "key": 41, - "repeat": 1, - "texture": 192 + "repeat": 1 } }, "id": 236, @@ -17203,115 +17203,115 @@ "animations": { "0": { "count": 1, + "first_tile": 224, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 255, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 255 + "repeat": 0 }, "11": { "count": 5, + "first_tile": 240, + "id": 11, "interval": 2, - "key": 11, - "repeat": 0, - "texture": 240 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 237, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 237 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 237, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 237 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 233, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 233 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 234, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 234 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 235, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 235 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 236, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 236 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 225, + "id": 2, "interval": 5, - "key": 2, - "repeat": 1, - "texture": 225 + "repeat": 1 }, "25": { "count": 10, + "first_tile": 245, + "id": 25, "interval": 5, - "key": 25, - "repeat": 1, - "texture": 245 + "repeat": 1 }, "26": { "count": 10, + "first_tile": 245, + "id": 26, "interval": 5, - "key": 26, - "repeat": 1, - "texture": 245 + "repeat": 1 }, "3": { "count": 8, + "first_tile": 225, + "id": 3, "interval": 5, - "key": 3, - "repeat": 1, - "texture": 225 + "repeat": 1 }, "33": { "count": 1, + "first_tile": 245, + "id": 33, "interval": 1, - "key": 33, - "repeat": 0, - "texture": 245 + "repeat": 0 }, "7": { "count": 1, + "first_tile": 218, + "id": 7, "interval": 1, - "key": 7, - "repeat": 0, - "texture": 218 + "repeat": 0 }, "8": { "count": 6, + "first_tile": 218, + "id": 8, "interval": 5, - "key": 8, - "repeat": 1, - "texture": 218 + "repeat": 1 } }, "id": 298, @@ -17321,80 +17321,80 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "12": { "count": 1, + "first_tile": 13, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 13, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 9, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 10, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 11, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 12, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 16, + "id": 19, "interval": 3, - "key": 19, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "3": { "count": 1, + "first_tile": 0, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "5": { "count": 5, + "first_tile": 75, + "id": 5, "interval": 3, - "key": 5, - "repeat": 0, - "texture": 75 + "repeat": 0 } }, "id": 268, @@ -17404,66 +17404,66 @@ "animations": { "0": { "count": 1, + "first_tile": 16, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 20, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 20 + "repeat": 0 }, "19": { "count": 3, + "first_tile": 21, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 21 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 32, + "id": 2, "interval": 8, - "key": 2, - "repeat": 1, - "texture": 32 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 17, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 17 + "repeat": 0 }, "38": { "count": 3, + "first_tile": 29, + "id": 38, "interval": 4, - "key": 38, - "repeat": 1, - "texture": 29 + "repeat": 1 }, "39": { "count": 2, + "first_tile": 38, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 38 + "repeat": 0 }, "40": { "count": 5, + "first_tile": 24, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 24 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 16, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 16 + "repeat": 0 } }, "id": 269, @@ -17473,66 +17473,66 @@ "animations": { "0": { "count": 1, + "first_tile": 40, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 40 + "repeat": 0 }, "1": { "count": 1, + "first_tile": 44, + "id": 1, "interval": 1, - "key": 1, - "repeat": 0, - "texture": 44 + "repeat": 0 }, "19": { "count": 3, + "first_tile": 45, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 45 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 56, + "id": 2, "interval": 8, - "key": 2, - "repeat": 1, - "texture": 56 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 41, + "id": 22, "interval": 4, - "key": 22, - "repeat": 0, - "texture": 41 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 51, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 51 + "repeat": 0 }, "39": { "count": 3, + "first_tile": 48, + "id": 39, "interval": 4, - "key": 39, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "40": { "count": 3, + "first_tile": 52, + "id": 40, "interval": 4, - "key": 40, - "repeat": 0, - "texture": 52 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 40, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 40 + "repeat": 0 } }, "id": 270, @@ -17542,143 +17542,143 @@ "animations": { "0": { "count": 1, + "first_tile": 128, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 128 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 149, + "id": 10, "interval": 4, - "key": 10, - "repeat": 1, - "texture": 149 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 141, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 141, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 141 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 138, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 138 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 137, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 137 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 140, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 140 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 139, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 139 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 160, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 160 + "repeat": 0 }, "2": { "count": 6, + "first_tile": 129, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 176, + "id": 23, "interval": 6, - "key": 23, - "repeat": 0, - "texture": 176 + "repeat": 0 }, "27": { "count": 3, + "first_tile": 144, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 144 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 146, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 146 + "repeat": 0 }, "3": { "count": 3, + "first_tile": 182, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 182 + "repeat": 0 }, "32": { "count": 6, + "first_tile": 129, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 129 + "repeat": 1 }, "41": { "count": 4, + "first_tile": 186, + "id": 41, "interval": 8, - "key": 41, - "repeat": 1, - "texture": 186 + "repeat": 1 }, "45": { "count": 5, + "first_tile": 165, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 165 + "repeat": 0 }, "46": { "count": 5, + "first_tile": 170, + "id": 46, "interval": 4, - "key": 46, - "repeat": 0, - "texture": 170 + "repeat": 0 }, "5": { "count": 1, + "first_tile": 185, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 185 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 146, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 146 + "repeat": 0 } }, "id": 901, @@ -17698,101 +17698,101 @@ "animations": { "0": { "count": 1, + "first_tile": 21, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 21 + "repeat": 0 }, "10": { "count": 4, + "first_tile": 76, + "id": 10, "interval": 5, - "key": 10, - "repeat": 1, - "texture": 76 + "repeat": 1 }, "13": { "count": 3, + "first_tile": 50, + "id": 13, "interval": 6, - "key": 13, - "repeat": 0, - "texture": 50 + "repeat": 0 }, "19": { "count": 7, + "first_tile": 42, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 42 + "repeat": 0 }, "2": { "count": 12, + "first_tile": 56, + "id": 2, "interval": 10, - "key": 2, - "repeat": 1, - "texture": 56 + "repeat": 1 }, "22": { "count": 3, + "first_tile": 29, + "id": 22, "interval": 6, - "key": 22, - "repeat": 0, - "texture": 29 + "repeat": 0 }, "27": { "count": 2, + "first_tile": 50, + "id": 27, "interval": 6, - "key": 27, - "repeat": 0, - "texture": 50 + "repeat": 0 }, "28": { "count": 2, + "first_tile": 53, + "id": 28, "interval": 6, - "key": 28, - "repeat": 0, - "texture": 53 + "repeat": 0 }, "3": { "count": 1, + "first_tile": 22, + "id": 3, "interval": 1, - "key": 3, - "repeat": 0, - "texture": 22 + "repeat": 0 }, "32": { "count": 12, + "first_tile": 56, + "id": 32, "interval": 7, - "key": 32, - "repeat": 1, - "texture": 56 + "repeat": 1 }, "45": { "count": 1, + "first_tile": 55, + "id": 45, "interval": 6, - "key": 45, - "repeat": 0, - "texture": 55 + "repeat": 0 }, "46": { "count": -4, + "first_tile": 79, + "id": 46, "interval": 5, - "key": 46, - "repeat": 1, - "texture": 79 + "repeat": 1 }, "5": { "count": 1, + "first_tile": 22, + "id": 5, "interval": 1, - "key": 5, - "repeat": 0, - "texture": 22 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 52, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 52 + "repeat": 0 } }, "id": 902, @@ -17802,143 +17802,143 @@ "animations": { "0": { "count": 1, + "first_tile": 192, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 192 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 213, + "id": 10, "interval": 4, - "key": 10, - "repeat": 1, - "texture": 213 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 205, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 205 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 205, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 205 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 202, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 202 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 201, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 201 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 204, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 204 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 203, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 203 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 224, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 224 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 193, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 193 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 240, + "id": 23, "interval": 6, - "key": 23, - "repeat": 0, - "texture": 240 + "repeat": 0 }, "27": { "count": 3, + "first_tile": 208, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 208 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 210, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 210 + "repeat": 0 }, "3": { "count": 4, + "first_tile": 246, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 246 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 193, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 193 + "repeat": 1 }, "41": { "count": 1, + "first_tile": 249, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 249 + "repeat": 0 }, "45": { "count": 5, + "first_tile": 229, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 229 + "repeat": 0 }, "46": { "count": 5, + "first_tile": 234, + "id": 46, "interval": 4, - "key": 46, - "repeat": 0, - "texture": 234 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 250, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 250 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 210, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 210 + "repeat": 0 } }, "id": 903, @@ -17948,143 +17948,143 @@ "animations": { "0": { "count": 1, + "first_tile": 64, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 64 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 85, + "id": 10, "interval": 4, - "key": 10, - "repeat": 1, - "texture": 85 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 77, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 77 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 77, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 77 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 74, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 74 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 73, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 73 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 76, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 76 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 75, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 75 + "repeat": 0 }, "19": { "count": 5, + "first_tile": 96, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 96 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 65, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 65 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 112, + "id": 23, "interval": 6, - "key": 23, - "repeat": 0, - "texture": 112 + "repeat": 0 }, "27": { "count": 3, + "first_tile": 80, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 80 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 82, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 82 + "repeat": 0 }, "3": { "count": 4, + "first_tile": 118, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 118 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 65, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 65 + "repeat": 1 }, "41": { "count": 1, + "first_tile": 121, + "id": 41, "interval": 1, - "key": 41, - "repeat": 0, - "texture": 121 + "repeat": 0 }, "45": { "count": 5, + "first_tile": 101, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 101 + "repeat": 0 }, "46": { "count": 5, + "first_tile": 106, + "id": 46, "interval": 4, - "key": 46, - "repeat": 0, - "texture": 106 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 122, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 122 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 82, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 82 + "repeat": 0 } }, "id": 900, @@ -18094,143 +18094,143 @@ "animations": { "0": { "count": 1, + "first_tile": 0, + "id": 0, "interval": 1, - "key": 0, - "repeat": 0, - "texture": 0 + "repeat": 0 }, "10": { "count": 7, + "first_tile": 21, + "id": 10, "interval": 4, - "key": 10, - "repeat": 1, - "texture": 21 + "repeat": 1 }, "12": { "count": 1, + "first_tile": 13, + "id": 12, "interval": 1, - "key": 12, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "13": { "count": 1, + "first_tile": 13, + "id": 13, "interval": 1, - "key": 13, - "repeat": 0, - "texture": 13 + "repeat": 0 }, "15": { "count": 1, + "first_tile": 10, + "id": 15, "interval": 1, - "key": 15, - "repeat": 0, - "texture": 10 + "repeat": 0 }, "16": { "count": 1, + "first_tile": 9, + "id": 16, "interval": 1, - "key": 16, - "repeat": 0, - "texture": 9 + "repeat": 0 }, "17": { "count": 1, + "first_tile": 12, + "id": 17, "interval": 1, - "key": 17, - "repeat": 0, - "texture": 12 + "repeat": 0 }, "18": { "count": 1, + "first_tile": 11, + "id": 18, "interval": 1, - "key": 18, - "repeat": 0, - "texture": 11 + "repeat": 0 }, "19": { "count": 4, + "first_tile": 44, + "id": 19, "interval": 4, - "key": 19, - "repeat": 0, - "texture": 44 + "repeat": 0 }, "2": { "count": 8, + "first_tile": 1, + "id": 2, "interval": 4, - "key": 2, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "23": { "count": 6, + "first_tile": 48, + "id": 23, "interval": 6, - "key": 23, - "repeat": 0, - "texture": 48 + "repeat": 0 }, "27": { "count": 3, + "first_tile": 16, + "id": 27, "interval": 4, - "key": 27, - "repeat": 0, - "texture": 16 + "repeat": 0 }, "28": { "count": 3, + "first_tile": 18, + "id": 28, "interval": 4, - "key": 28, - "repeat": 0, - "texture": 18 + "repeat": 0 }, "3": { "count": 4, + "first_tile": 32, + "id": 3, "interval": 4, - "key": 3, - "repeat": 0, - "texture": 32 + "repeat": 0 }, "32": { "count": 8, + "first_tile": 1, + "id": 32, "interval": 3, - "key": 32, - "repeat": 1, - "texture": 1 + "repeat": 1 }, "41": { "count": 4, + "first_tile": 40, + "id": 41, "interval": 4, - "key": 41, - "repeat": 1, - "texture": 40 + "repeat": 1 }, "45": { "count": 4, + "first_tile": 58, + "id": 45, "interval": 4, - "key": 45, - "repeat": 0, - "texture": 58 + "repeat": 0 }, "46": { "count": 4, + "first_tile": 54, + "id": 46, "interval": 4, - "key": 46, - "repeat": 0, - "texture": 54 + "repeat": 0 }, "5": { "count": 4, + "first_tile": 36, + "id": 5, "interval": 4, - "key": 5, - "repeat": 0, - "texture": 36 + "repeat": 0 }, "9": { "count": 1, + "first_tile": 18, + "id": 9, "interval": 1, - "key": 9, - "repeat": 0, - "texture": 18 + "repeat": 0 } }, "id": 899, diff --git a/docs/game_data/lua_enums.txt b/docs/game_data/lua_enums.txt index 76d53d635..cd2ac1265 100644 --- a/docs/game_data/lua_enums.txt +++ b/docs/game_data/lua_enums.txt @@ -91,9 +91,9 @@ DRAW_LAYER = { WINDOW = 2 } DROP = { - ALIENQUEEN_ALIENBLAST = 184, - ALIENQUEEN_ALIENBLAST_RE = 186, - ALIENQUEEN_ALIENBLAST_RI = 185, + ALIENQUEEN_ALIENBLAST = 187, + ALIENQUEEN_ALIENBLAST_RE = 189, + ALIENQUEEN_ALIENBLAST_RI = 188, ALTAR_DICE_CLIMBINGGLOVES = 0, ALTAR_DICE_COOKEDTURKEY = 1, ALTAR_DICE_DIAMOND = 2, @@ -117,27 +117,30 @@ DROP = { ALTAR_USHABTI_HIREDHAND = 17, ALTAR_USHABTI_TURKEY = 15, ALTAR_USHABTI_VAMPIRE = 16, - ANUBIS2_ANUBIS_COFFIN = 159, + ANUBIS2_ANUBIS_COFFIN = 162, ANUBIS2_JETPACK = 23, - ANUBIS2_SPECIALSHOT_R = 189, + ANUBIS2_SPECIALSHOT_R = 192, ANUBIS_COFFIN_SORCERESS = 111, ANUBIS_COFFIN_VAMPIRE = 110, ANUBIS_COFFIN_WITCHDOCTOR = 112, ANUBIS_SCEPTER = 24, - ANUBIS_SPECIALSHOT_R = 188, - ARROWTRAP_WOODENARROW = 156, - AXOLOTL_BUBBLE = 177, + ANUBIS_SPECIALSHOT_R = 191, + ARROWTRAP_WOODENARROW = 159, + AXOLOTL_BUBBLE = 180, BEG_BOMBBAG = 25, BEG_TELEPACK = 27, BEG_TRUECROWN = 26, - BONEBLOCK_BONES = 194, - BONEBLOCK_SKELETON = 192, - BONEBLOCK_SKULL = 193, + BONEBLOCK_BONES = 197, + BONEBLOCK_SKELETON = 195, + BONEBLOCK_SKULL = 196, BONEPILE_SKELETONKEY = 28, BONEPILE_SKULL = 29, CANDLE_NUGGET = 150, - CATMUMMY_CURSINGCLOUD = 187, + CATMUMMY_CURSINGCLOUD = 190, CATMUMMY_DIAMOND = 122, + CHALLENGESTAR_CLONEGUN = 156, + CHALLENGESTAR_ELIXIR = 157, + CHALLENGESUN_PLAYERBAG = 158, CHEST_BOMB = 141, CHEST_EMERALD = 136, CHEST_LEPRECHAUN = 140, @@ -145,12 +148,12 @@ DROP = { CHEST_SAPPHIRE = 137, CHEST_SMALLEMERALD = 135, CHEST_SMALLRUBY = 139, - CLONEGUN_SHOT = 169, - COBRA_ACIDSPIT = 180, + CLONEGUN_SHOT = 172, + COBRA_ACIDSPIT = 183, COFFIN_SKULL = 153, - COOKEDTURKEY_HEALTH = 206, - COOKFIRE_CAVEMAN_1 = 190, - COOKFIRE_CAVEMAN_2 = 191, + COOKEDTURKEY_HEALTH = 209, + COOKFIRE_CAVEMAN_1 = 193, + COOKFIRE_CAVEMAN_2 = 194, COOKFIRE_TORCH = 151, CROCMAN_TELEPACK = 30, CROCMAN_TELEPORTER = 31, @@ -164,49 +167,49 @@ DROP = { EGGSAC_GRUB_3 = 117, EMBED_NUGGET = 134, FACTORY_GENERATOR_SCRAP = 94, - FIREBUG_FIREBALL = 179, + FIREBUG_FIREBALL = 182, FLOORSTYLEDCOG_NUGGET = 131, - FLOOR_DIAMOND = 201, - FLOOR_EMBED_GOLD = 203, - FLOOR_EMBED_GOLD_BIG = 204, - FLOOR_EMERALD = 199, - FLOOR_RUBY = 202, - FLOOR_SAPPHIRE = 200, - FREEZERAY_SHOT = 168, + FLOOR_DIAMOND = 204, + FLOOR_EMBED_GOLD = 206, + FLOOR_EMBED_GOLD_BIG = 207, + FLOOR_EMERALD = 202, + FLOOR_RUBY = 205, + FLOOR_SAPPHIRE = 203, + FREEZERAY_SHOT = 171, GHIST_GOLDCOIN = 64, GHOSTJAR_DIAMOND = 32, GHOST_DIAMOND = 33, - GIANTFOOD_HEALTH = 207, + GIANTFOOD_HEALTH = 210, GIANTFROG_FROG = 113, GIANTFROG_TADPOLE = 114, GIANTSPIDER_PASTE = 34, - GIANTSPIDER_WEBSHOT = 161, - GIANTSPIDER_WEB_LEFT = 195, - GIANTSPIDER_WEB_RIGHT = 196, + GIANTSPIDER_WEBSHOT = 164, + GIANTSPIDER_WEB_LEFT = 198, + GIANTSPIDER_WEB_RIGHT = 199, GOLDENMONKEY_NUGGET = 38, GOLDENMONKEY_SMALLEMERALD = 35, GOLDENMONKEY_SMALLRUBY = 37, GOLDENMONKEY_SMALLSAPPHIRE = 36, HANGINGSPIDER_WEBGUN = 39, - HERMITCRAB_ACIDBUBBLE = 182, + HERMITCRAB_ACIDBUBBLE = 185, HUMPHEAD_HIREDHAND = 123, - HUNDUN_FIREBALL = 178, + HUNDUN_FIREBALL = 181, ICECAVE_BOULDER = 40, - ICE_ALIVE_EMBEDDED_ON_ICE = 198, - IMP_LAVAPOT = 197, + ICE_ALIVE_EMBEDDED_ON_ICE = 201, + IMP_LAVAPOT = 200, JIANGSHIASSASSIN_SPIKESHOES = 41, JIANGSHI_SPRINGSHOES = 42, - KAPALA_HEALTH = 209, + KAPALA_HEALTH = 212, KINGU_FEMALE_JIANGSHI = 46, KINGU_JIANGSHI = 45, KINGU_OCTOPUS = 44, KINGU_TABLETOFDESTINY = 43, LAMASSU_DIAMOND = 127, LAMASSU_EMERALD = 126, - LAMASSU_LASERSHOT = 172, + LAMASSU_LASERSHOT = 175, LAMASSU_RUBY = 125, LAMASSU_SAPPHIRE = 124, - LASERTRAP_SHOT = 158, + LASERTRAP_SHOT = 161, LAVAMANDER_RUBY = 121, LAVAPOT_MAGMAMAN = 120, LEPRECHAUN_CLOVER = 47, @@ -215,40 +218,40 @@ DROP = { MATTOCK_BROKENMATTOCK = 48, MOLE_MATTOCK = 49, MOSQUITO_HOVERPACK = 50, - MOTHERSTATUE_HEALTH = 205, + MOTHERSTATUE_HEALTH = 208, MUMMY_DIAMOND = 51, - MUMMY_FLY = 160, + MUMMY_FLY = 163, NECROMANCER_RUBY = 52, - OCTOPUS_INKSPIT = 181, - OLMEC_BOMB = 162, + OCTOPUS_INKSPIT = 184, + OLMEC_BOMB = 165, OLMEC_CAVEMAN_1 = 53, OLMEC_CAVEMAN_2 = 54, OLMEC_CAVEMAN_3 = 55, OLMEC_SISTERS_BOMBBOX = 155, OLMEC_SISTERS_ROPEPILE = 154, - OLMEC_UFO = 163, + OLMEC_UFO = 166, OSIRIS_EMERALDS = 56, OSIRIS_PORTAL = 58, OSIRIS_TABLETOFDESTINY = 57, - PANGXIE_ACIDBUBBLE = 183, + PANGXIE_ACIDBUBBLE = 186, PANGXIE_WOODENSHIELD = 59, - PLASMACANNON_SHOT = 167, - POISONEDARROWTRAP_WOODENARROW = 157, + PLASMACANNON_SHOT = 170, + POISONEDARROWTRAP_WOODENARROW = 160, POTOFGOLD_GOLDCOIN = 147, - QILIN_FIREBALL = 176, + QILIN_FIREBALL = 179, QUEENBEE_ROYALJELLY = 60, QUILLBACK_BOMBBAG = 118, QUILLBACK_COOKEDTURKEY = 119, REDLANTERN_SMALLNUGGET = 149, ROBOT_METALSHIELD = 61, - ROCKDOG_FIREBALL = 175, - ROYALJELLY_HEALTH = 208, + ROCKDOG_FIREBALL = 178, + ROYALJELLY_HEALTH = 211, SACRIFICE_EGGPLANT = 105, SACRIFICE_IDOL = 102, SACRIFICE_PRESENT = 103, SACRIFICE_ROCK = 104, - SCEPTER_ANUBISSPECIALSHOT = 165, - SCEPTER_PLAYERSHOT = 166, + SCEPTER_ANUBISSPECIALSHOT = 168, + SCEPTER_PLAYERSHOT = 169, SCRAP_ALIEN = 100, SCRAP_COBRA = 98, SCRAP_SCORPION = 99, @@ -257,12 +260,12 @@ DROP = { SHOPKEEPER_GENERATOR_1 = 95, SHOPKEEPER_GOLDBAR = 63, SHOPKEEPER_GOLDCOIN = 62, - SHOTGUN_BULLET = 170, + SHOTGUN_BULLET = 173, SKELETON_SKELETONKEY = 65, SKELETON_SKULL = 66, SKULLDROPTRAP_SKULL = 152, SLIDINGWALL_NUGGET = 133, - SORCERESS_DAGGERSHOT = 173, + SORCERESS_DAGGERSHOT = 176, SORCERESS_RUBY = 67, SPARROW_ROPEPILE = 68, SPARROW_SKELETONKEY = 69, @@ -278,13 +281,13 @@ DROP = { TIAMAT_SCORPION = 79, TIAMAT_SHOT = 80, TIAMAT_SNAKE = 81, - TIAMAT_TIAMATSHOT = 174, + TIAMAT_TIAMATSHOT = 177, TIAMAT_UFO = 82, TIAMAT_YETI = 83, TORCH_SMALLNUGGET = 84, TURKEY_COOKEDTURKEY = 85, UFO_ALIEN = 101, - UFO_LASERSHOT = 171, + UFO_LASERSHOT = 174, UFO_PARACHUTE = 86, USHABTI_QILIN = 146, VAMPIRE_CAPE = 87, @@ -298,7 +301,7 @@ DROP = { YAMA_GIANTFOOD = 107, YANG_KEY = 108, YETIKING_FREEZERAY = 91, - YETIKING_ICESPIRE = 164, + YETIKING_ICESPIRE = 167, YETIQUEEN_POWERPACK = 92, YETI_PITCHERSMITT = 93 } @@ -328,6 +331,9 @@ DYNAMIC_TEXTURE = { ENTITY_OVERRIDE = { ACTIVATE = 25, APPLY_FRICTION = 84, + APPLY_METADATA = 28, + APPLY_VELOCITY = 42, + CALCULATE_JUMP_VELOCITY = 40, CAN_BE_PUSHED = 10, CAN_ENTER = 46, CAN_JUMP = 37, @@ -343,10 +349,16 @@ ENTITY_OVERRIDE = { ENTER = 42, ENTER_ATTEMPT = 40, FALL = 83, + FLIP = 16, FLOOR_UPDATE = 38, FREEZE = 52, - FRICTION = 17, + FRICTION = 19, + GENERATE_STOMP_DAMAGE_PARTICLES = 8, + GET_COLLISION_INFO = 38, + GET_DAMAGE = 43, + GET_DAMAGE_SOUND = 50, GET_HELD_ENTITY = 22, + GET_METADATA = 27, HIDE_HUD = 41, INIT = 36, INITIALIZE = 75, @@ -355,6 +367,7 @@ ENTITY_OVERRIDE = { IS_UNLOCKED = 45, KILL = 3, LEDGE_GRAB = 31, + LIBERATE_FROM_SHOP = 35, LIGHT_LEVEL = 44, LIGHT_ON_FIRE = 53, ON_COLLISION1 = 4, @@ -364,8 +377,14 @@ ENTITY_OVERRIDE = { PICKED_UP_BY = 68, PICK_UP = 67, PROCESS_INPUT = 78, + REMOVE_ITEM = 21, + RESET_DRAW_DEPTH = 18, + SET_AS_SOUND_SOURCE = 20, SET_CURSED = 54, + SET_DRAW_DEPTH = 17, SET_INVISIBLE = 15, + SET_STANDING_ON = 59, + SPRINT_FACTOR = 39, STANDING_ON = 60, STOMPED_BY = 61, STOMP_DAMAGE = 43, @@ -1772,6 +1791,11 @@ GHOST_BEHAVIOR = { SMALL_SAD = 2, SMALL_SURPRISED = 1 } +HOTKEY_TYPE = { + GLOBAL = 1, + INPUT = 2, + NORMAL = 0 +} HUNDUNFLAGS = { BIRDHEADEMERGED = 2, BIRDHEADSHOTLAST = 16, @@ -2008,6 +2032,11 @@ KEY = { Y = 89, Z = 90 } +KEY_TYPE = { + ANY = 0, + KEYBOARD = 255, + MOUSE = 1024 +} LAYER = { BACK = 1, BOTH = -128, diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index f07860d8e..c89bf6b5a 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -4153,6 +4153,9 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@class Web : Movable ---@field decay_rate number @Is subtracted from the color alpha every frame after the `stand_counter` is more than 300.
Entity automatically dies when the alpha is less than 0.1 +---@class Scepter : Movable + ---@field cooldown integer + ---@class LiquidSurface : Movable ---@field glow_radius number ---@field sine_pos number @@ -6875,9 +6878,9 @@ DRAW_LAYER = { } ---@alias DRAW_LAYER integer DROP = { - ALIENQUEEN_ALIENBLAST = 184, - ALIENQUEEN_ALIENBLAST_RE = 186, - ALIENQUEEN_ALIENBLAST_RI = 185, + ALIENQUEEN_ALIENBLAST = 187, + ALIENQUEEN_ALIENBLAST_RE = 189, + ALIENQUEEN_ALIENBLAST_RI = 188, ALTAR_DICE_CLIMBINGGLOVES = 0, ALTAR_DICE_COOKEDTURKEY = 1, ALTAR_DICE_DIAMOND = 2, @@ -6901,27 +6904,30 @@ DROP = { ALTAR_USHABTI_HIREDHAND = 17, ALTAR_USHABTI_TURKEY = 15, ALTAR_USHABTI_VAMPIRE = 16, - ANUBIS2_ANUBIS_COFFIN = 159, + ANUBIS2_ANUBIS_COFFIN = 162, ANUBIS2_JETPACK = 23, - ANUBIS2_SPECIALSHOT_R = 189, + ANUBIS2_SPECIALSHOT_R = 192, ANUBIS_COFFIN_SORCERESS = 111, ANUBIS_COFFIN_VAMPIRE = 110, ANUBIS_COFFIN_WITCHDOCTOR = 112, ANUBIS_SCEPTER = 24, - ANUBIS_SPECIALSHOT_R = 188, - ARROWTRAP_WOODENARROW = 156, - AXOLOTL_BUBBLE = 177, + ANUBIS_SPECIALSHOT_R = 191, + ARROWTRAP_WOODENARROW = 159, + AXOLOTL_BUBBLE = 180, BEG_BOMBBAG = 25, BEG_TELEPACK = 27, BEG_TRUECROWN = 26, - BONEBLOCK_BONES = 194, - BONEBLOCK_SKELETON = 192, - BONEBLOCK_SKULL = 193, + BONEBLOCK_BONES = 197, + BONEBLOCK_SKELETON = 195, + BONEBLOCK_SKULL = 196, BONEPILE_SKELETONKEY = 28, BONEPILE_SKULL = 29, CANDLE_NUGGET = 150, - CATMUMMY_CURSINGCLOUD = 187, + CATMUMMY_CURSINGCLOUD = 190, CATMUMMY_DIAMOND = 122, + CHALLENGESTAR_CLONEGUN = 156, + CHALLENGESTAR_ELIXIR = 157, + CHALLENGESUN_PLAYERBAG = 158, CHEST_BOMB = 141, CHEST_EMERALD = 136, CHEST_LEPRECHAUN = 140, @@ -6929,12 +6935,12 @@ DROP = { CHEST_SAPPHIRE = 137, CHEST_SMALLEMERALD = 135, CHEST_SMALLRUBY = 139, - CLONEGUN_SHOT = 169, - COBRA_ACIDSPIT = 180, + CLONEGUN_SHOT = 172, + COBRA_ACIDSPIT = 183, COFFIN_SKULL = 153, - COOKEDTURKEY_HEALTH = 206, - COOKFIRE_CAVEMAN_1 = 190, - COOKFIRE_CAVEMAN_2 = 191, + COOKEDTURKEY_HEALTH = 209, + COOKFIRE_CAVEMAN_1 = 193, + COOKFIRE_CAVEMAN_2 = 194, COOKFIRE_TORCH = 151, CROCMAN_TELEPACK = 30, CROCMAN_TELEPORTER = 31, @@ -6948,49 +6954,49 @@ DROP = { EGGSAC_GRUB_3 = 117, EMBED_NUGGET = 134, FACTORY_GENERATOR_SCRAP = 94, - FIREBUG_FIREBALL = 179, + FIREBUG_FIREBALL = 182, FLOORSTYLEDCOG_NUGGET = 131, - FLOOR_DIAMOND = 201, - FLOOR_EMBED_GOLD = 203, - FLOOR_EMBED_GOLD_BIG = 204, - FLOOR_EMERALD = 199, - FLOOR_RUBY = 202, - FLOOR_SAPPHIRE = 200, - FREEZERAY_SHOT = 168, + FLOOR_DIAMOND = 204, + FLOOR_EMBED_GOLD = 206, + FLOOR_EMBED_GOLD_BIG = 207, + FLOOR_EMERALD = 202, + FLOOR_RUBY = 205, + FLOOR_SAPPHIRE = 203, + FREEZERAY_SHOT = 171, GHIST_GOLDCOIN = 64, GHOSTJAR_DIAMOND = 32, GHOST_DIAMOND = 33, - GIANTFOOD_HEALTH = 207, + GIANTFOOD_HEALTH = 210, GIANTFROG_FROG = 113, GIANTFROG_TADPOLE = 114, GIANTSPIDER_PASTE = 34, - GIANTSPIDER_WEBSHOT = 161, - GIANTSPIDER_WEB_LEFT = 195, - GIANTSPIDER_WEB_RIGHT = 196, + GIANTSPIDER_WEBSHOT = 164, + GIANTSPIDER_WEB_LEFT = 198, + GIANTSPIDER_WEB_RIGHT = 199, GOLDENMONKEY_NUGGET = 38, GOLDENMONKEY_SMALLEMERALD = 35, GOLDENMONKEY_SMALLRUBY = 37, GOLDENMONKEY_SMALLSAPPHIRE = 36, HANGINGSPIDER_WEBGUN = 39, - HERMITCRAB_ACIDBUBBLE = 182, + HERMITCRAB_ACIDBUBBLE = 185, HUMPHEAD_HIREDHAND = 123, - HUNDUN_FIREBALL = 178, + HUNDUN_FIREBALL = 181, ICECAVE_BOULDER = 40, - ICE_ALIVE_EMBEDDED_ON_ICE = 198, - IMP_LAVAPOT = 197, + ICE_ALIVE_EMBEDDED_ON_ICE = 201, + IMP_LAVAPOT = 200, JIANGSHIASSASSIN_SPIKESHOES = 41, JIANGSHI_SPRINGSHOES = 42, - KAPALA_HEALTH = 209, + KAPALA_HEALTH = 212, KINGU_FEMALE_JIANGSHI = 46, KINGU_JIANGSHI = 45, KINGU_OCTOPUS = 44, KINGU_TABLETOFDESTINY = 43, LAMASSU_DIAMOND = 127, LAMASSU_EMERALD = 126, - LAMASSU_LASERSHOT = 172, + LAMASSU_LASERSHOT = 175, LAMASSU_RUBY = 125, LAMASSU_SAPPHIRE = 124, - LASERTRAP_SHOT = 158, + LASERTRAP_SHOT = 161, LAVAMANDER_RUBY = 121, LAVAPOT_MAGMAMAN = 120, LEPRECHAUN_CLOVER = 47, @@ -6999,40 +7005,40 @@ DROP = { MATTOCK_BROKENMATTOCK = 48, MOLE_MATTOCK = 49, MOSQUITO_HOVERPACK = 50, - MOTHERSTATUE_HEALTH = 205, + MOTHERSTATUE_HEALTH = 208, MUMMY_DIAMOND = 51, - MUMMY_FLY = 160, + MUMMY_FLY = 163, NECROMANCER_RUBY = 52, - OCTOPUS_INKSPIT = 181, - OLMEC_BOMB = 162, + OCTOPUS_INKSPIT = 184, + OLMEC_BOMB = 165, OLMEC_CAVEMAN_1 = 53, OLMEC_CAVEMAN_2 = 54, OLMEC_CAVEMAN_3 = 55, OLMEC_SISTERS_BOMBBOX = 155, OLMEC_SISTERS_ROPEPILE = 154, - OLMEC_UFO = 163, + OLMEC_UFO = 166, OSIRIS_EMERALDS = 56, OSIRIS_PORTAL = 58, OSIRIS_TABLETOFDESTINY = 57, - PANGXIE_ACIDBUBBLE = 183, + PANGXIE_ACIDBUBBLE = 186, PANGXIE_WOODENSHIELD = 59, - PLASMACANNON_SHOT = 167, - POISONEDARROWTRAP_WOODENARROW = 157, + PLASMACANNON_SHOT = 170, + POISONEDARROWTRAP_WOODENARROW = 160, POTOFGOLD_GOLDCOIN = 147, - QILIN_FIREBALL = 176, + QILIN_FIREBALL = 179, QUEENBEE_ROYALJELLY = 60, QUILLBACK_BOMBBAG = 118, QUILLBACK_COOKEDTURKEY = 119, REDLANTERN_SMALLNUGGET = 149, ROBOT_METALSHIELD = 61, - ROCKDOG_FIREBALL = 175, - ROYALJELLY_HEALTH = 208, + ROCKDOG_FIREBALL = 178, + ROYALJELLY_HEALTH = 211, SACRIFICE_EGGPLANT = 105, SACRIFICE_IDOL = 102, SACRIFICE_PRESENT = 103, SACRIFICE_ROCK = 104, - SCEPTER_ANUBISSPECIALSHOT = 165, - SCEPTER_PLAYERSHOT = 166, + SCEPTER_ANUBISSPECIALSHOT = 168, + SCEPTER_PLAYERSHOT = 169, SCRAP_ALIEN = 100, SCRAP_COBRA = 98, SCRAP_SCORPION = 99, @@ -7041,12 +7047,12 @@ DROP = { SHOPKEEPER_GENERATOR_1 = 95, SHOPKEEPER_GOLDBAR = 63, SHOPKEEPER_GOLDCOIN = 62, - SHOTGUN_BULLET = 170, + SHOTGUN_BULLET = 173, SKELETON_SKELETONKEY = 65, SKELETON_SKULL = 66, SKULLDROPTRAP_SKULL = 152, SLIDINGWALL_NUGGET = 133, - SORCERESS_DAGGERSHOT = 173, + SORCERESS_DAGGERSHOT = 176, SORCERESS_RUBY = 67, SPARROW_ROPEPILE = 68, SPARROW_SKELETONKEY = 69, @@ -7062,13 +7068,13 @@ DROP = { TIAMAT_SCORPION = 79, TIAMAT_SHOT = 80, TIAMAT_SNAKE = 81, - TIAMAT_TIAMATSHOT = 174, + TIAMAT_TIAMATSHOT = 177, TIAMAT_UFO = 82, TIAMAT_YETI = 83, TORCH_SMALLNUGGET = 84, TURKEY_COOKEDTURKEY = 85, UFO_ALIEN = 101, - UFO_LASERSHOT = 171, + UFO_LASERSHOT = 174, UFO_PARACHUTE = 86, USHABTI_QILIN = 146, VAMPIRE_CAPE = 87, @@ -7082,7 +7088,7 @@ DROP = { YAMA_GIANTFOOD = 107, YANG_KEY = 108, YETIKING_FREEZERAY = 91, - YETIKING_ICESPIRE = 164, + YETIKING_ICESPIRE = 167, YETIQUEEN_POWERPACK = 92, YETI_PITCHERSMITT = 93 } @@ -7115,6 +7121,9 @@ DYNAMIC_TEXTURE = { ENTITY_OVERRIDE = { ACTIVATE = 25, APPLY_FRICTION = 84, + APPLY_METADATA = 28, + APPLY_VELOCITY = 42, + CALCULATE_JUMP_VELOCITY = 40, CAN_BE_PUSHED = 10, CAN_ENTER = 46, CAN_JUMP = 37, @@ -7130,10 +7139,16 @@ ENTITY_OVERRIDE = { ENTER = 42, ENTER_ATTEMPT = 40, FALL = 83, + FLIP = 16, FLOOR_UPDATE = 38, FREEZE = 52, - FRICTION = 17, + FRICTION = 19, + GENERATE_STOMP_DAMAGE_PARTICLES = 8, + GET_COLLISION_INFO = 38, + GET_DAMAGE = 43, + GET_DAMAGE_SOUND = 50, GET_HELD_ENTITY = 22, + GET_METADATA = 27, HIDE_HUD = 41, INIT = 36, INITIALIZE = 75, @@ -7142,6 +7157,7 @@ ENTITY_OVERRIDE = { IS_UNLOCKED = 45, KILL = 3, LEDGE_GRAB = 31, + LIBERATE_FROM_SHOP = 35, LIGHT_LEVEL = 44, LIGHT_ON_FIRE = 53, ON_COLLISION1 = 4, @@ -7151,8 +7167,14 @@ ENTITY_OVERRIDE = { PICKED_UP_BY = 68, PICK_UP = 67, PROCESS_INPUT = 78, + REMOVE_ITEM = 21, + RESET_DRAW_DEPTH = 18, + SET_AS_SOUND_SOURCE = 20, SET_CURSED = 54, + SET_DRAW_DEPTH = 17, SET_INVISIBLE = 15, + SET_STANDING_ON = 59, + SPRINT_FACTOR = 39, STANDING_ON = 60, STOMPED_BY = 61, STOMP_DAMAGE = 43, @@ -8569,6 +8591,12 @@ GHOST_BEHAVIOR = { SMALL_SURPRISED = 1 } ---@alias GHOST_BEHAVIOR integer +HOTKEY_TYPE = { + GLOBAL = 1, + INPUT = 2, + NORMAL = 0 +} +---@alias HOTKEY_TYPE integer HUNDUNFLAGS = { BIRDHEADEMERGED = 2, BIRDHEADSHOTLAST = 16, @@ -8814,6 +8842,12 @@ KEY = { Z = 90 } ---@alias KEY integer +KEY_TYPE = { + ANY = 0, + KEYBOARD = 255, + MOUSE = 1024 +} +---@alias KEY_TYPE integer LAYER = { BACK = 1, BOTH = -128, diff --git a/docs/game_data/vtable_sizes.csv b/docs/game_data/vtable_sizes.csv index 701f60c50..6c4006715 100644 --- a/docs/game_data/vtable_sizes.csv +++ b/docs/game_data/vtable_sizes.csv @@ -1,10 +1,10 @@ -TypeID,Name,vtable offset,~Entity,create_rendering_info,handle_state_machine,kill,on_collision1,destroy,apply_texture,format_shopitem_name,generate_stomp_damage_particles,get_type_field_a8,block_pushing_related,v11,v12,check_type_properties_flags_19,get_type_field_60,set_invisible,handle_turning_left,set_draw_depth,resume_ai,friction,v20,remove_item_ptr,get_held_entity,v23,trigger_action,on_attempt_shop_purchase,on_collision2,get_metadata,apply_metadata,on_walked_on_by,on_walked_off_by,v31,on_stood_on_by,toggle_backlayer_illumination,v34,liberate_from_shop,apply_db,END OF ENTITY,can_jump,v38,sprint_factor,calculate_jump_height,get_animation_map,apply_velocity,stomp_damage,stomp_damage_trampoline,is_on_fire,v46,v47,on_damage,on_hit,v50,stun,freeze,light_on_fire,set_cursed,on_spiderweb_collision,set_last_owner_uid_b127,get_last_owner_uid,check_out_of_bounds,v59,standing_on,on_stomped_on_by,on_thrown_by,on_clonegunshot_hit,get_type_id,doesnt_have_spikeshoes,is_player_mount_or_monster,pick_up,picked_up_by,drop,add_money,apply_movement,damage_entity,is_monster_or_player,initialize,check_is_falling,handle_stun_transition_animation,process_input,post_collision_damage_related,picked_up,hired_hand_related,generate_fall_poof_particles,handle_fall_logic,apply_friction,boss_related,tusk_last_owner_uid_related,gravity_related,v87,v88,stack_plus_28_is_0,on_crushed_by,on_fall_onto,on_instakill_death,END OF MOVABLE,v93,v94,v95,v96,v97,v98,v99,v100,v101,v102,v103,v104,v105,v106,v107,v108,v109, +TypeID,Name,vtable offset,~Entity,create_rendering_info,update_state_machine,kill,on_collision1,destroy,apply_texture,format_shopitem_name,generate_stomp_damage_particles,get_type_field_a8,can_be_pushed,v11,is_in_liquid,check_type_properties_flags_19,get_type_field_60,set_invisible,flip,set_draw_depth,reset_draw_depth,friction,set_as_sound_source,remove_item,get_held_entity,v23,trigger_action,activate,on_collision2,get_metadata,apply_metadata,on_walked_on_by,on_walked_off_by,on_ledge_grab,on_stood_on_by,toggle_backlayer_illumination,v34,liberate_from_shop,apply_db,END OF ENTITY,can_jump,get_collision_info,sprint_factor,calculate_jump_velocity,get_animation_map,apply_velocity,get_damage,get_stomp_damage,is_on_fire,attack,thrown_into,damage,on_hit,get_damage_sound,stun,freeze,light_on_fire,set_cursed,on_spiderweb_collision,set_last_owner_uid_b127,get_last_owner_uid,check_out_of_bounds,set_standing_on,standing_on,on_stomped_on_by,on_thrown_by,copy_extra_info,get_type_id,doesnt_have_spikeshoes,is_player_mount_or_monster,pick_up,can_be_picked_up_by,drop,collect_treasure,apply_movement,damage_entity,v73,is_powerup_capable,initialize,check_is_falling,v77,process_input,post_collision_damage_related,on_picked_up,on_release,generate_fall_poof_particles,handle_fall_logic,apply_friction,can_break_block,break_block,v87,v88,v89,on_crushed_by,on_fall_onto,on_instakill_death,END OF MOVABLE,v93,v94,v95,v96,v97,v98,v99,v100,v101,v102,v103,v104,v105,v106,v107,v108,v109, 1,ENT_TYPE_FLOOR_BORDERTILE,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 2,ENT_TYPE_FLOOR_BORDERTILE_METAL,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 3,ENT_TYPE_FLOOR_BORDERTILE_OCTOPUS,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 4,ENT_TYPE_FLOOR_GENERIC,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 5,ENT_TYPE_FLOOR_SURFACE,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 -6,ENT_TYPE_FLOOR_SURFACE_HIDDEN,48206,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,ret,0x2287cbd0,0x2287d100,ret 0,ret true,ret,ret,ret,ret,0x228bff80,0x2287d100,ret 0,0x228bfe80,ret,ret,0x228bfe90,0x2292e2c0,0x228bdfb0,ret true,ret 0,ret 0,ret,ret,0x228ee610,0x22997220,0x228bdfb0,0x228c4340,ret 0,ret 0,0x22999730,0x22999750,0x22999aa0,0x228c6ab0,0x22999f90,ret true,ret 0,ret 0,0x22999fc0,ret,0x2299a010,0x228c6ab0,0x228bdfb0,0x2289e280,0x2299bf40,0x2299d580,0x2299d8a0,0x229a3840,0x229a3b00,0xffff817ed3580173,0xffff817fd3580000,0x228a9670 +6,ENT_TYPE_FLOOR_SURFACE_HIDDEN,48206,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,ret,0x2287cbd0,0x2287d100,ret 0,ret true,ret,ret,ret,ret,0x228bff80,0x2287d100,ret 0,0x228bfe80,ret,ret,0x228bfe90,0x2292e2c0,0x228bdfb0,ret true,ret 0,ret 0,ret,ret,0x228ee610,0x22997220,0x228bdfb0,0x228c4340,ret 0,ret 0,0x22999730,0x22999750,0x22999aa0,0x228c6ab0,0x22999f90,ret true,ret 0,ret 0,0x22999fc0,ret,0x2299a010,0x228c6ab0,0x228bdfb0,0x2289e280,0x2299bf40,0x2299d580,0x2299d8a0,0x229a3840,0x229a3b00,0xffff817e81650173,0xffff817f81650000,0x228a9670 7,ENT_TYPE_FLOOR_BASECAMP_SINGLEBED,10626,0x2287aed0,0x227fcd90,ret,0x2297d3f0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x2297d600,0x2297d680,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 8,ENT_TYPE_FLOOR_BASECAMP_DININGTABLE,10626,0x2287aed0,0x227fcd90,ret,0x2297d3f0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x2297d600,0x2297d680,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 9,ENT_TYPE_FLOOR_BASECAMP_LONGTABLE,10626,0x2287aed0,0x227fcd90,ret,0x2297d3f0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x2297d600,0x2297d680,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 @@ -91,7 +91,7 @@ TypeID,Name,vtable offset,~Entity,create_rendering_info,handle_state_machine,kil 90,ENT_TYPE_FLOOR_FORCEFIELD_TOP,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 91,ENT_TYPE_FLOOR_HORIZONTAL_FORCEFIELD,8946,0x2287aed0,0x227fcd90,0x22974270,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x22974960,0x227fd790,0x227fd930,0x227fd950,0x22974760,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22974240,END OF ENTITY,0x22928d00,ret,0x2287cbd0 92,ENT_TYPE_FLOOR_HORIZONTAL_FORCEFIELD_TOP,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 -93,ENT_TYPE_FLOOR_PEN,48142,0x2287aed0,0x227fcd90,ret,0x22978910,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x22978990,0x9098015d85e000c,0x68011d65b030c,0x68011d3620009,0x78011d3620009,0x98013d3600008,0x98013d362000a,0xa8013d363000b,0xbf7f8009d363000b,0xffff800a12d80000 +93,ENT_TYPE_FLOOR_PEN,48142,0x2287aed0,0x227fcd90,ret,0x22978910,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x22978990,0x9098015866b000c,0x680118468030c,0x68011816f0009,0x78011816f0009,0x98013816d0008,0x98013816f000a,0xa80138170000b,0xbf7f80098170000b,0xffff8009c0e50000 94,ENT_TYPE_FLOOR_TOMB,8906,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x2298cc30,END OF ENTITY,0x22928d00,0x2292c410,0x2288b9e0 95,ENT_TYPE_FLOOR_YAMA_PLATFORM,8866,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x2288d9c0,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 96,ENT_TYPE_FLOOR_EMPRESS_GRAVE,8826,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2288b9e0 @@ -811,7 +811,7 @@ TypeID,Name,vtable offset,~Entity,create_rendering_info,handle_state_machine,kil 841,ENT_TYPE_BG_EGGSAC_STAINS,2460,0x2287aed0,0x227fcd90,ret,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,ret,END OF ENTITY 844,ENT_TYPE_LOGICAL_CONSTELLATION,2840,0x2287aed0,0x227fcd90,ret,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,0x229f53f0,END OF ENTITY 845,ENT_TYPE_LOGICAL_SHOOTING_STARS_SPAWNER,2802,0x2287aed0,0x227fcd90,0x22a004c0,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,0x22a004b0,END OF ENTITY -846,ENT_TYPE_LOGICAL_DOOR,48710,0x2287aed0,0x227fcd90,0x229f8090,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,ret,END OF ENTITY,0xffff800a12d80000,0x403f800a13580000 +846,ENT_TYPE_LOGICAL_DOOR,48710,0x2287aed0,0x227fcd90,0x229f8090,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,ret,END OF ENTITY,0xffff8009c0e50000,0x403f8009c1650000 847,ENT_TYPE_LOGICAL_DOOR_AMBIENT_SOUND,2764,0x2287aed0,0x227fcd90,0x229f83c0,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,0x229f8360,END OF ENTITY 848,ENT_TYPE_LOGICAL_BLACKMARKET_DOOR,2726,0x2287aed0,0x227fcd90,0x229f8090,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,0x229f3af0,END OF ENTITY 849,ENT_TYPE_LOGICAL_ARROW_TRAP_TRIGGER,48672,0x2287aed0,0x227fcd90,0x229f35f0,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,0x229f3a20,ret 0,ret,0x229f3a40,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,ret,END OF ENTITY diff --git a/docs/src/includes/_casting.md b/docs/src/includes/_casting.md index a914292b6..f914b21e7 100644 --- a/docs/src/includes/_casting.md +++ b/docs/src/includes/_casting.md @@ -285,6 +285,7 @@ For reference, the available `as_` functions are listed below: - as_roomowner - as_rubble - as_scarab +- as_scepter - as_sceptershot - as_scorpion - as_shield diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 1099f5cc9..13db5465c 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -7220,6 +7220,15 @@ Derived from [Entity](#Entity) [Movable](#Movable) Type | Name | Description ---- | ---- | ----------- +### Scepter + +Derived from [Entity](#Entity) [Movable](#Movable) + + +Type | Name | Description +---- | ---- | ----------- +int | [cooldown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=cooldown) | + ### ScepterShot Derived from [Entity](#Entity) [Movable](#Movable) [LightEmitter](#LightEmitter) diff --git a/src/info_dump/main.cpp b/src/info_dump/main.cpp index 0c13f84c0..2d9250139 100644 --- a/src/info_dump/main.cpp +++ b/src/info_dump/main.cpp @@ -963,10 +963,10 @@ void get_vtables() const auto base_off = (size_t)Memory::get().exe(); - file << "TypeID,Name,vtable offset,~Entity,create_rendering_info,handle_state_machine,kill,on_collision1,destroy,apply_texture,format_shopitem_name,generate_stomp_damage_particles,get_type_field_a8,block_pushing_related,v11,v12,check_type_properties_flags_19,get_type_field_60,set_invisible,handle_turning_left,set_draw_depth,resume_ai,friction,v20,remove_item_ptr," - "get_held_entity,v23,trigger_action,on_attempt_shop_purchase,on_collision2,get_metadata,apply_metadata,on_walked_on_by,on_walked_off_by,v31,on_stood_on_by,toggle_backlayer_illumination,v34,liberate_from_shop,apply_db,END OF ENTITY,can_jump,v38,sprint_factor,calculate_jump_height,get_animation_map,apply_velocity,stomp_damage,stomp_damage_trampoline,is_on_fire,v46,v47," - "on_damage,on_hit,v50,stun,freeze,light_on_fire,set_cursed,on_spiderweb_collision,set_last_owner_uid_b127,get_last_owner_uid,check_out_of_bounds,v59,standing_on,on_stomped_on_by,on_thrown_by,on_clonegunshot_hit,get_type_id,doesnt_have_spikeshoes,is_player_mount_or_monster,pick_up,picked_up_by,drop,add_money,apply_movement,damage_entity,is_monster_or_player," - "initialize,check_is_falling,handle_stun_transition_animation,process_input,post_collision_damage_related,picked_up,hired_hand_related,generate_fall_poof_particles,handle_fall_logic,apply_friction,boss_related,tusk_last_owner_uid_related,gravity_related,v87,v88,stack_plus_28_is_0,on_crushed_by,on_fall_onto,on_instakill_death,END OF MOVABLE,v93,v94,v95,v96,v97,v98,v99,v100,v101,v102,v103,v104,v105,v106,v107,v108,v109,"; + file << "TypeID,Name,vtable offset,~Entity,create_rendering_info,update_state_machine,kill,on_collision1,destroy,apply_texture,format_shopitem_name,generate_stomp_damage_particles,get_type_field_a8,can_be_pushed,v11,is_in_liquid,check_type_properties_flags_19,get_type_field_60,set_invisible,flip,set_draw_depth,reset_draw_depth,friction,set_as_sound_source,remove_item," + "get_held_entity,v23,trigger_action,activate,on_collision2,get_metadata,apply_metadata,on_walked_on_by,on_walked_off_by,on_ledge_grab,on_stood_on_by,toggle_backlayer_illumination,v34,liberate_from_shop,apply_db,END OF ENTITY,can_jump,get_collision_info,sprint_factor,calculate_jump_velocity,get_animation_map,apply_velocity,get_damage,get_stomp_damage,is_on_fire,attack,thrown_into," + "damage,on_hit,get_damage_sound,stun,freeze,light_on_fire,set_cursed,on_spiderweb_collision,set_last_owner_uid_b127,get_last_owner_uid,check_out_of_bounds,set_standing_on,standing_on,on_stomped_on_by,on_thrown_by,copy_extra_info,get_type_id,doesnt_have_spikeshoes,is_player_mount_or_monster,pick_up,can_be_picked_up_by,drop,collect_treasure,apply_movement,damage_entity,v73," + "is_powerup_capable,initialize,check_is_falling,v77,process_input,post_collision_damage_related,on_picked_up,on_release,generate_fall_poof_particles,handle_fall_logic,apply_friction,can_break_block,break_block,v87,v88,v89,on_crushed_by,on_fall_onto,on_instakill_death,END OF MOVABLE,v93,v94,v95,v96,v97,v98,v99,v100,v101,v102,v103,v104,v105,v106,v107,v108,v109,"; file << std::endl; int idx = 0; From b9acb98c8800060be37b5712ea8ba9a150cec4d7 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 12 Sep 2024 22:04:34 +0200 Subject: [PATCH 08/21] exposing more vitrual functions and hooks --- docs/game_data/lua_enums.txt | 10 ++ docs/game_data/spel2.lua | 99 ++++++++++++++----- docs/src/includes/_enums.md | 11 ++- docs/src/includes/_types.md | 89 ++++++++++++----- src/game_api/entity.hpp | 2 +- src/game_api/entity_db.hpp | 3 +- src/game_api/movable.hpp | 21 +--- src/game_api/script/usertypes/entity_lua.cpp | 60 +++++++---- src/game_api/script/usertypes/vtables_lua.cpp | 61 +++++++----- 9 files changed, 236 insertions(+), 120 deletions(-) diff --git a/docs/game_data/lua_enums.txt b/docs/game_data/lua_enums.txt index cd2ac1265..ca863618f 100644 --- a/docs/game_data/lua_enums.txt +++ b/docs/game_data/lua_enums.txt @@ -332,9 +332,14 @@ ENTITY_OVERRIDE = { ACTIVATE = 25, APPLY_FRICTION = 84, APPLY_METADATA = 28, + APPLY_MOVEMENT = 71, APPLY_VELOCITY = 42, + ATTACK = 46, + BREAK_BLOCK = 86, CALCULATE_JUMP_VELOCITY = 40, + CAN_BE_PICKED_UP_BY = 68, CAN_BE_PUSHED = 10, + CAN_BREAK_BLOCK = 85, CAN_ENTER = 46, CAN_JUMP = 37, CHECK_OUT_OF_BOUNDS = 58, @@ -353,6 +358,7 @@ ENTITY_OVERRIDE = { FLOOR_UPDATE = 38, FREEZE = 52, FRICTION = 19, + GENERATE_FALL_POOF_PARTICLES = 82, GENERATE_STOMP_DAMAGE_PARTICLES = 8, GET_COLLISION_INFO = 38, GET_DAMAGE = 43, @@ -362,8 +368,10 @@ ENTITY_OVERRIDE = { HIDE_HUD = 41, INIT = 36, INITIALIZE = 75, + INSTAKILL_DEATH = 92, IS_IN_LIQUID = 12, IS_ON_FIRE = 45, + IS_POWERUP_CAPABLE = 74, IS_UNLOCKED = 45, KILL = 3, LEDGE_GRAB = 31, @@ -377,6 +385,7 @@ ENTITY_OVERRIDE = { PICKED_UP_BY = 68, PICK_UP = 67, PROCESS_INPUT = 78, + RELEASE = 81, REMOVE_ITEM = 21, RESET_DRAW_DEPTH = 18, SET_AS_SOUND_SOURCE = 20, @@ -391,6 +400,7 @@ ENTITY_OVERRIDE = { STOOD_ON = 32, STUN = 51, THROWN_BY = 62, + THROWN_INTO = 47, TRIGGER_ACTION = 24, UPDATE_STATE_MACHINE = 2, WALKED_OFF = 30, diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index c89bf6b5a..b666426e2 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -2426,13 +2426,18 @@ function PRNG:random(min, max) end ---@field search_flags integer @MASK ---@field width number ---@field height number + ---@field draw_depth integer ---@field offsetx number ---@field offsety number ---@field hitboxx number ---@field hitboxy number - ---@field draw_depth integer + ---@field default_shape SHAPE + ---@field default_hitbox_enabled boolean ---@field collision2_mask integer @MASK, will only call collision2 when colliding with entities that match this mask. ---@field collision_mask integer @MASK used for collision with floors, walls etc. + ---@field default_flags integer + ---@field default_more_flags integer + ---@field properties_flags integer ---@field friction number ---@field elasticity number ---@field weight number @@ -2441,21 +2446,20 @@ function PRNG:random(min, max) end ---@field sprint_factor number ---@field jump number ---@field default_color Color + ---@field texture TEXTURE + ---@field tilex integer + ---@field tiley integer ---@field damage integer ---@field life integer ---@field sacrifice_value integer @Favor for sacrificing alive. Halved when dead (health == 0). ---@field blood_content integer - ---@field texture TEXTURE - ---@field animations table - ---@field properties_flags integer - ---@field default_flags integer - ---@field default_more_flags integer ---@field leaves_corpse_behind boolean + ---@field description STRINGID ---@field sound_killed_by_player integer ---@field sound_killed_by_other integer - ---@field description STRINGID - ---@field tilex integer - ---@field tiley integer + ---@field animations table + ---@field default_special_offsetx number + ---@field default_special_offsetx number ---@class RenderInfo ---@field x number @@ -2517,7 +2521,7 @@ function PRNG:random(min, max) end ---@field get_texture fun(self): TEXTURE ---@field set_texture fun(self, texture_id: TEXTURE): boolean @Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one ---@field set_draw_depth fun(self, draw_depth: integer, b3f: integer): nil - ---@field set_enable_turning fun(self, enabled: boolean): nil + ---@field reset_draw_depth fun(self): nil ---@field liberate_from_shop fun(self, clear_parrent: boolean): nil @`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 ---@field get_held_entity fun(self): Entity ---@field set_layer fun(self, layer: LAYER): nil @Moves the entity to specified layer, nothing else happens, so this does not emulate a door transition @@ -2535,9 +2539,12 @@ function PRNG:random(min, max) end ---@field get_items fun(self): integer[] ---@field is_in_liquid fun(self): boolean @Returns true if entity is in water/lava ---@field is_cursed fun(self): boolean + ---@field is_movable fun(self): boolean + ---@field can_be_pushed fun(self): boolean ---@field update fun(self): nil ---@field flip fun(self, left: boolean): nil - ---@field can_be_pushed fun(self): boolean + ---@field remove_item fun(self, entity: Entity, autokill_check: boolean): nil + ---@field apply_db fun(self): nil @Applies changes made in `entity.type` ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. @@ -2646,6 +2653,7 @@ function Entity:destroy_recursive() end ---@field buttons_previous BUTTON ---@field stand_counter integer ---@field jump_height_multiplier number @EntityDB.jump gets multiplied by this to get the jump + ---@field price integer ---@field owner_uid integer ---@field last_owner_uid integer ---@field current_animation Animation @@ -2669,7 +2677,6 @@ function Entity:destroy_recursive() end ---@field exit_invincibility_timer integer ---@field invincibility_frames_timer integer ---@field frozen_timer integer - ---@field price integer ---@field is_poisoned fun(self): boolean ---@field is_button_pressed fun(self, button: BUTTON): boolean ---@field is_button_held fun(self, button: BUTTON): boolean @@ -2677,7 +2684,7 @@ function Entity:destroy_recursive() end ---@field stun fun(self, framecount: integer): nil ---@field freeze fun(self, framecount: integer, ignore_lava: boolean): nil @Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time ---@field light_on_fire fun(self, time: integer): nil @Does not damage entity - ---@field set_cursed fun(self, b: boolean, effect: boolean?): nil @effect = true - plays the sound and spawn particle above entity + ---@field set_cursed fun(self, b: boolean, effect: boolean): nil ---@field drop fun(self): nil @Called when dropping or throwing ---@field pick_up fun(self, entity_to_pick_up: Entity): nil ---@field standing_on fun(self): Entity @@ -2685,6 +2692,9 @@ function Entity:destroy_recursive() end ---@field can_jump fun(self): boolean @Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. ---@field is_on_fire fun(self): boolean ---@field is_powerup_capable fun(self): boolean + ---@field can_be_picked_up_by fun(self, entity_picking_up: Entity, boolean: ): boolean + ---@field can_break_block fun(self, horizontal: boolean, block: Entity): boolean + ---@field break_block fun(self, camera_shake: boolean, block: Entity): nil ---@field damage fun(self, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean @Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer ---@field get_all_behaviors fun(self): integer[] @Get all available behavior ids ---@field set_behavior fun(self, behavior_id: integer): boolean @Set behavior, this is more than just state as it's an active function, for example climbing ladder is a behavior and it doesn't actually need ladder/rope entity
Returns false if entity doesn't have this behavior id @@ -2693,6 +2703,13 @@ function Entity:destroy_recursive() end ---@field reset_gravity fun(self): nil @Remove the gravity hook and reset to defaults ---@field set_position fun(self, to_x: number, to_y: number): nil @Set the absolute position of an entity and offset all rendering related things accordingly to teleport without any interpolation or graphical glitches. If the camera is focused on the entity, it is also moved. ---@field process_input fun(self): nil + ---@field calculate_jump_velocity fun(self, dont_ignore_liquid: boolean): number + ---@field apply_velocity fun(self, velocities: Vec2, ignore_weight: boolean): nil + ---@field get_damage fun(self): integer @Returns the damage that the entity deals + ---@field attack fun(self, victim: Entity): boolean @Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) + ---@field thrown_into fun(self, victim: Entity): boolean @Same as above, but for being thrown into something and potentially dealing damage that way + ---@field get_damage_sound fun(self, damage: DAMAGE_TYPE): integer @returns sound id for the damage taken, return 0 to make it silence + ---@field copy_extra_info fun(self, clone: Entity, some_entity_uid: integer): nil @Entities must be of the same type! ---@field cutscene CutsceneBehavior ---@field clear_cutscene fun(self): nil ---@field get_base_behavior fun(self, state_id: integer): VanillaMovableBehavior @Gets a vanilla behavior from this movable, needs to be called before `clear_behaviors`
but the returned values are still valid after a call to `clear_behaviors` @@ -2718,6 +2735,10 @@ function Entity:destroy_recursive() end ---@field set_post_get_damage fun(self, fun: fun(self: Movable): integer?): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_damage(Movable self)`
Virtual function docs:
Returns the damage that the entity deals ---@field set_pre_is_on_fire fun(self, fun: fun(self: Movable): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional is_on_fire(Movable self)` ---@field set_post_is_on_fire fun(self, fun: fun(self: Movable): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil is_on_fire(Movable self)` + ---@field set_pre_attack fun(self, fun: fun(self: Movable, victim: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional attack(Movable self, Entity victim)`
Virtual function docs:
Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) + ---@field set_post_attack fun(self, fun: fun(self: Movable, victim: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil attack(Movable self, Entity victim)`
Virtual function docs:
Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) + ---@field set_pre_thrown_into fun(self, fun: fun(self: Movable, victim: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional thrown_into(Movable self, Entity victim)`
Virtual function docs:
Same as above, but for being thrown into something and potentially dealing damage that way + ---@field set_post_thrown_into fun(self, fun: fun(self: Movable, victim: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil thrown_into(Movable self, Entity victim)`
Virtual function docs:
Same as above, but for being thrown into something and potentially dealing damage that way ---@field set_pre_damage fun(self, fun: fun(self: Movable, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional damage(Movable self, Entity damage_dealer, integer damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, integer unknown_damage_phase, integer stun_amount, integer iframes, boolean unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer ---@field set_post_damage fun(self, fun: fun(self: Movable, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, integer damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, integer unknown_damage_phase, integer stun_amount, integer iframes, boolean unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer ---@field set_pre_on_hit fun(self, fun: fun(self: Movable, damage_dealer: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. @@ -2732,40 +2753,54 @@ function Entity:destroy_recursive() end ---@field set_post_light_on_fire fun(self, fun: fun(self: Movable, time: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil light_on_fire(Movable self, integer time)`
Virtual function docs:
Does not damage entity ---@field set_pre_set_cursed fun(self, fun: fun(self: Movable, b: boolean, effect: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool set_cursed(Movable self, boolean b, boolean effect)` ---@field set_post_set_cursed fun(self, fun: fun(self: Movable, b: boolean, effect: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil set_cursed(Movable self, boolean b, boolean effect)` - ---@field set_pre_web_collision fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool web_collision(Movable self)` - ---@field set_post_web_collision fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil web_collision(Movable self)` + ---@field set_pre_web_collision fun(self, fun: fun(self: Movable, boolean: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool web_collision(Movable self, boolean boolean)` + ---@field set_post_web_collision fun(self, fun: fun(self: Movable, boolean: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil web_collision(Movable self, boolean boolean)` ---@field set_pre_check_out_of_bounds fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool check_out_of_bounds(Movable self)`
Virtual function docs:
Disable to not get killed outside level bounds. ---@field set_post_check_out_of_bounds fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil check_out_of_bounds(Movable self)`
Virtual function docs:
Disable to not get killed outside level bounds. ---@field set_pre_set_standing_on fun(self, fun: fun(self: Movable, entity_uid: integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool set_standing_on(Movable self, integer entity_uid)` ---@field set_post_set_standing_on fun(self, fun: fun(self: Movable, entity_uid: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil set_standing_on(Movable self, integer entity_uid)` ---@field set_pre_standing_on fun(self, fun: fun(self: Movable): Entity?): CallbackId @Hooks before the virtual function.
The callback signature is `optional standing_on(Movable self)` ---@field set_post_standing_on fun(self, fun: fun(self: Movable): Entity?): CallbackId @Hooks after the virtual function.
The callback signature is `nil standing_on(Movable self)` - ---@field set_pre_stomped_by fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool stomped_by(Movable self, Entity)` - ---@field set_post_stomped_by fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil stomped_by(Movable self, Entity)` - ---@field set_pre_thrown_by fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool thrown_by(Movable self, Entity)` - ---@field set_post_thrown_by fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil thrown_by(Movable self, Entity)` - ---@field set_pre_cloned_to fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool cloned_to(Movable self, Entity)` - ---@field set_post_cloned_to fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil cloned_to(Movable self, Entity)` + ---@field set_pre_stomped_by fun(self, fun: fun(self: Movable, stomper: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional stomped_by(Movable self, Entity stomper)` + ---@field set_post_stomped_by fun(self, fun: fun(self: Movable, stomper: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil stomped_by(Movable self, Entity stomper)` + ---@field set_pre_thrown_by fun(self, fun: fun(self: Movable, thrower: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool thrown_by(Movable self, Entity thrower)` + ---@field set_post_thrown_by fun(self, fun: fun(self: Movable, thrower: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil thrown_by(Movable self, Entity thrower)` + ---@field set_pre_cloned_to fun(self, fun: fun(self: Movable, some_entity_uid: Entity clone integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool cloned_to(Movable self, Entity clone integer some_entity_uid)` + ---@field set_post_cloned_to fun(self, fun: fun(self: Movable, some_entity_uid: Entity clone integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil cloned_to(Movable self, Entity clone integer some_entity_uid)` ---@field set_pre_pick_up fun(self, fun: fun(self: Movable, entity_to_pick_up: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool pick_up(Movable self, Entity entity_to_pick_up)` ---@field set_post_pick_up fun(self, fun: fun(self: Movable, entity_to_pick_up: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil pick_up(Movable self, Entity entity_to_pick_up)` - ---@field set_pre_picked_up_by fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool picked_up_by(Movable self, Entity)` - ---@field set_post_picked_up_by fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil picked_up_by(Movable self, Entity)` + ---@field set_pre_can_be_picked_up_by fun(self, fun: fun(self: Movable, entity_picking_up: Entity, boolean: ): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional can_be_picked_up_by(Movable self, Entity entity_picking_up, boolean)` + ---@field set_post_can_be_picked_up_by fun(self, fun: fun(self: Movable, entity_picking_up: Entity, boolean: ): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil can_be_picked_up_by(Movable self, Entity entity_picking_up, boolean)` ---@field set_pre_drop fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool drop(Movable self)`
Virtual function docs:
Called when dropping or throwing ---@field set_post_drop fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil drop(Movable self)`
Virtual function docs:
Called when dropping or throwing ---@field set_pre_collect_treasure fun(self, fun: fun(self: Movable, value: integer, treasure: ENT_TYPE): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional collect_treasure(Movable self, integer value, ENT_TYPE treasure)`
Virtual function docs:
Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. ---@field set_post_collect_treasure fun(self, fun: fun(self: Movable, value: integer, treasure: ENT_TYPE): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil collect_treasure(Movable self, integer value, ENT_TYPE treasure)`
Virtual function docs:
Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. + ---@field set_pre_apply_movement fun(self, fun: fun(self: Movable, integer: , integer: , integer: ): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional apply_movement(Movable self, integer, integer, integer)` + ---@field set_post_apply_movement fun(self, fun: fun(self: Movable, integer: , integer: , integer: ): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil apply_movement(Movable self, integer, integer, integer)` + ---@field set_pre_is_powerup_capable fun(self, fun: fun(self: Movable): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional is_powerup_capable(Movable self)` + ---@field set_post_is_powerup_capable fun(self, fun: fun(self: Movable): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil is_powerup_capable(Movable self)` ---@field set_pre_initialize fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool initialize(Movable self)` ---@field set_post_initialize fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil initialize(Movable self)` ---@field set_pre_process_input fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool process_input(Movable self)` ---@field set_post_process_input fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil process_input(Movable self)` ---@field set_pre_picked_up fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool picked_up(Movable self)` ---@field set_post_picked_up fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil picked_up(Movable self)` - ---@field set_pre_fall fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool fall(Movable self)` - ---@field set_post_fall fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil fall(Movable self)` + ---@field set_pre_release fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool release(Movable self)` + ---@field set_post_release fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil release(Movable self)` + ---@field set_pre_generate_fall_poof_particles fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool generate_fall_poof_particles(Movable self)` + ---@field set_post_generate_fall_poof_particles fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil generate_fall_poof_particles(Movable self)` + ---@field set_pre_fall fun(self, fun: fun(self: Movable, number: number): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool fall(Movable self, number number)` + ---@field set_post_fall fun(self, fun: fun(self: Movable, number: number): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil fall(Movable self, number number)` ---@field set_pre_apply_friction fun(self, fun: fun(self: Movable, number: , vertical: boolean, number: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool apply_friction(Movable self, number, boolean vertical, number)` ---@field set_post_apply_friction fun(self, fun: fun(self: Movable, number: , vertical: boolean, number: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil apply_friction(Movable self, number, boolean vertical, number)` - ---@field set_pre_crush fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool crush(Movable self, Entity)` - ---@field set_post_crush fun(self, fun: fun(self: Movable, Entity: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil crush(Movable self, Entity)` + ---@field set_pre_can_break_block fun(self, fun: fun(self: Movable, horizontal: boolean, block: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional can_break_block(Movable self, boolean horizontal, Entity block)` + ---@field set_post_can_break_block fun(self, fun: fun(self: Movable, horizontal: boolean, block: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil can_break_block(Movable self, boolean horizontal, Entity block)` + ---@field set_pre_break_block fun(self, fun: fun(self: Movable, camera_shake: boolean, block: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool break_block(Movable self, boolean camera_shake, Entity block)` + ---@field set_post_break_block fun(self, fun: fun(self: Movable, camera_shake: boolean, block: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil break_block(Movable self, boolean camera_shake, Entity block)` + ---@field set_pre_crush fun(self, fun: fun(self: Movable, entity: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool crush(Movable self, Entity entity)` + ---@field set_post_crush fun(self, fun: fun(self: Movable, entity: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil crush(Movable self, Entity entity)` + ---@field set_pre_instakill_death fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool instakill_death(Movable self)` + ---@field set_post_instakill_death fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil instakill_death(Movable self)` local Movable = nil ---Move a movable according to its velocity, can disable gravity ---Will also update `movable.animation_frame` and various timers and counters @@ -7122,9 +7157,14 @@ ENTITY_OVERRIDE = { ACTIVATE = 25, APPLY_FRICTION = 84, APPLY_METADATA = 28, + APPLY_MOVEMENT = 71, APPLY_VELOCITY = 42, + ATTACK = 46, + BREAK_BLOCK = 86, CALCULATE_JUMP_VELOCITY = 40, + CAN_BE_PICKED_UP_BY = 68, CAN_BE_PUSHED = 10, + CAN_BREAK_BLOCK = 85, CAN_ENTER = 46, CAN_JUMP = 37, CHECK_OUT_OF_BOUNDS = 58, @@ -7143,6 +7183,7 @@ ENTITY_OVERRIDE = { FLOOR_UPDATE = 38, FREEZE = 52, FRICTION = 19, + GENERATE_FALL_POOF_PARTICLES = 82, GENERATE_STOMP_DAMAGE_PARTICLES = 8, GET_COLLISION_INFO = 38, GET_DAMAGE = 43, @@ -7152,8 +7193,10 @@ ENTITY_OVERRIDE = { HIDE_HUD = 41, INIT = 36, INITIALIZE = 75, + INSTAKILL_DEATH = 92, IS_IN_LIQUID = 12, IS_ON_FIRE = 45, + IS_POWERUP_CAPABLE = 74, IS_UNLOCKED = 45, KILL = 3, LEDGE_GRAB = 31, @@ -7167,6 +7210,7 @@ ENTITY_OVERRIDE = { PICKED_UP_BY = 68, PICK_UP = 67, PROCESS_INPUT = 78, + RELEASE = 81, REMOVE_ITEM = 21, RESET_DRAW_DEPTH = 18, SET_AS_SOUND_SOURCE = 20, @@ -7181,6 +7225,7 @@ ENTITY_OVERRIDE = { STOOD_ON = 32, STUN = 51, THROWN_BY = 62, + THROWN_INTO = 47, TRIGGER_ACTION = 24, UPDATE_STATE_MACHINE = 2, WALKED_OFF = 30, diff --git a/docs/src/includes/_enums.md b/docs/src/includes/_enums.md index 5dd0d4144..4065f64a7 100644 --- a/docs/src/includes/_enums.md +++ b/docs/src/includes/_enums.md @@ -262,6 +262,8 @@ Name | Data | Description [APPLY_VELOCITY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.APPLY_VELOCITY) | 42 | [GET_DAMAGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GET_DAMAGE) | 43 | [IS_ON_FIRE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.IS_ON_FIRE) | 45 | +[ATTACK](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ATTACK) | 46 | +[THROWN_INTO](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.THROWN_INTO) | 47 | [DAMAGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.DAMAGE) | 48 | [ON_HIT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ON_HIT) | 49 | [GET_DAMAGE_SOUND](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GET_DAMAGE_SOUND) | 50 | @@ -277,15 +279,22 @@ Name | Data | Description [THROWN_BY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.THROWN_BY) | 62 | [CLONED_TO](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CLONED_TO) | 63 | [PICK_UP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.PICK_UP) | 67 | -[PICKED_UP_BY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.PICKED_UP_BY) | 68 | +[CAN_BE_PICKED_UP_BY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CAN_BE_PICKED_UP_BY) | 68 | [DROP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.DROP) | 69 | [COLLECT_TREASURE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.COLLECT_TREASURE) | 70 | +[APPLY_MOVEMENT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.APPLY_MOVEMENT) | 71 | +[IS_POWERUP_CAPABLE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.IS_POWERUP_CAPABLE) | 74 | [INITIALIZE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.INITIALIZE) | 75 | [PROCESS_INPUT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.PROCESS_INPUT) | 78 | [PICKED_UP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.PICKED_UP) | 80 | +[RELEASE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.RELEASE) | 81 | +[GENERATE_FALL_POOF_PARTICLES](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GENERATE_FALL_POOF_PARTICLES) | 82 | [FALL](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.FALL) | 83 | [APPLY_FRICTION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.APPLY_FRICTION) | 84 | +[CAN_BREAK_BLOCK](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CAN_BREAK_BLOCK) | 85 | +[BREAK_BLOCK](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.BREAK_BLOCK) | 86 | [CRUSH](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CRUSH) | 90 | +[INSTAKILL_DEATH](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.INSTAKILL_DEATH) | 92 | [FLOOR_UPDATE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.FLOOR_UPDATE) | 38 | [ENTER_ATTEMPT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ENTER_ATTEMPT) | 40 | [HIDE_HUD](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.HIDE_HUD) | 41 | diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 13db5465c..00f0a1de2 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -456,13 +456,18 @@ Type | Name | Description int | [search_flags](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=search_flags) | [MASK](#MASK) float | [width](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=width) | float | [height](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=height) | +int | [draw_depth](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_depth) | float | [offsetx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=offsetx) | float | [offsety](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=offsety) | float | [hitboxx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=hitboxx) | float | [hitboxy](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=hitboxy) | -int | [draw_depth](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_depth) | +[SHAPE](#SHAPE) | [default_shape](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_shape) | +bool | [default_hitbox_enabled](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_hitbox_enabled) | int | [collision2_mask](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collision2_mask) | [MASK](#MASK), will only call collision2 when colliding with entities that match this mask. int | [collision_mask](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collision_mask) | [MASK](#MASK) used for collision with floors, walls etc. +int | [default_flags](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_flags) | +int | [default_more_flags](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_more_flags) | +int | [properties_flags](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=properties_flags) | float | [friction](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=friction) | float | [elasticity](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=elasticity) | float | [weight](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=weight) | @@ -471,21 +476,20 @@ float | [max_speed](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=max float | [sprint_factor](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sprint_factor) | float | [jump](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=jump) | [Color](#Color) | [default_color](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_color) | +[TEXTURE](#TEXTURE) | [texture](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=texture) | +int | [tilex](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tilex) | +int | [tiley](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tiley) | int | [damage](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=damage) | int | [life](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=life) | int | [sacrifice_value](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sacrifice_value) | Favor for sacrificing alive. Halved when dead (health == 0). int | [blood_content](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=blood_content) | -[TEXTURE](#TEXTURE) | [texture](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=texture) | -map<int, [Animation](#Animation)> | [animations](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=animations) | -int | [properties_flags](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=properties_flags) | -int | [default_flags](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_flags) | -int | [default_more_flags](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_more_flags) | bool | [leaves_corpse_behind](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=leaves_corpse_behind) | +[STRINGID](#Aliases) | [description](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=description) | int | [sound_killed_by_player](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound_killed_by_player) | int | [sound_killed_by_other](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound_killed_by_other) | -[STRINGID](#Aliases) | [description](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=description) | -int | [tilex](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tilex) | -int | [tiley](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tiley) | +map<int, [Animation](#Animation)> | [animations](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=animations) | +float | [default_special_offsetx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_special_offsetx) | +float | [default_special_offsetx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_special_offsetx) | ### HudInventory @@ -4233,7 +4237,7 @@ bool | [overlaps_with(Entity other)](https://github.com/spelunky-fyi/overlunky/s [TEXTURE](#TEXTURE) | [get_texture()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_texture) | bool | [set_texture(TEXTURE texture_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_texture) | Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one nil | [set_draw_depth(int draw_depth, int b3f)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_draw_depth) | -nil | [set_enable_turning(bool enabled)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_enable_turning) | +nil | [reset_draw_depth()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=reset_draw_depth) | nil | [liberate_from_shop(bool clear_parrent)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=liberate_from_shop) | `clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 [Entity](#Entity) | [get_held_entity()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_held_entity) | nil | [set_layer(LAYER layer)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_layer) | Moves the entity to specified layer, nothing else happens, so this does not emulate a door transition @@ -4251,13 +4255,16 @@ nil | [set_invisible(bool value)](https://github.com/spelunky-fyi/overlunky/sear vector<int> | [get_items()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_items) | bool | [is_in_liquid()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_in_liquid) | Returns true if entity is in water/lava bool | [is_cursed()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_cursed) | +bool | [is_movable()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_movable) | +bool | [can_be_pushed()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=can_be_pushed) | nil | [kill_recursive(bool destroy_corpse, Entity responsible, optional mask, array ent_types, RECURSIVE_MODE rec_mode)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=kill_recursive) | Kill entity along with all entities attached to it. Be aware that for example killing push block with this function will also kill anything on top of it, any items, players, monsters etc.
To avoid that, you can inclusively or exclusively limit certain [MASK](#MASK) and [ENT_TYPE](#ENT_TYPE). Note: the function will first check mask, if the entity doesn't match, it will look in the provided [ENT_TYPE](#ENT_TYPE)'s
destroy_corpse and responsible are the standard parameters for the kill function nil | [kill_recursive(bool destroy_corpse, Entity responsible)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=kill_recursive) | Short for using [RECURSIVE_MODE](#RECURSIVE_MODE).NONE nil | [destroy_recursive(optional mask, array ent_types, RECURSIVE_MODE rec_mode)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destroy_recursive) | Destroy entity along with all entities attached to it. Be aware that for example destroying push block with this function will also destroy anything on top of it, any items, players, monsters etc.
To avoid that, you can inclusively or exclusively limit certain [MASK](#MASK) and [ENT_TYPE](#ENT_TYPE). Note: the function will first check the mask, if the entity doesn't match, it will look in the provided [ENT_TYPE](#ENT_TYPE)'s nil | [destroy_recursive()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destroy_recursive) | Short for using [RECURSIVE_MODE](#RECURSIVE_MODE).NONE nil | [update()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=update) | nil | [flip(bool left)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=flip) | -bool | [can_be_pushed()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=can_be_pushed) | +nil | [remove_item(Entity entity, bool autokill_check)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=remove_item) | +nil | [apply_db()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apply_db) | Applies changes made in `entity.type` [CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. [CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. @@ -6886,6 +6893,7 @@ float | [movey](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=movey) [BUTTON](#BUTTON) | [buttons_previous](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=buttons_previous) | int | [stand_counter](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=stand_counter) | float | [jump_height_multiplier](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=jump_height_multiplier) | [EntityDB](#EntityDB).jump gets multiplied by this to get the jump +int | [price](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=price) | int | [owner_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=owner_uid) | int | [last_owner_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=last_owner_uid) | [Animation](#Animation) | [current_animation](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=current_animation) | @@ -6909,7 +6917,6 @@ int | [onfire_effect_timer](https://github.com/spelunky-fyi/overlunky/search?l=L int | [exit_invincibility_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=exit_invincibility_timer) | int | [invincibility_frames_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=invincibility_frames_timer) | int | [frozen_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=frozen_timer) | -int | [price](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=price) | bool | [is_poisoned()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_poisoned) | bool | [is_button_pressed(BUTTON button)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_button_pressed) | bool | [is_button_held(BUTTON button)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_button_held) | @@ -6917,7 +6924,7 @@ bool | [is_button_released(BUTTON button)](https://github.com/spelunky-fyi/overl nil | [stun(int framecount)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=stun) | nil | [freeze(int framecount, bool ignore_lava)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=freeze) | Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time nil | [light_on_fire(int time)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=light_on_fire) | Does not damage entity -nil | [set_cursed(bool b, optional effect)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_cursed) | effect = true - plays the sound and spawn particle above entity +nil | [set_cursed(bool b, bool effect)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_cursed) | nil | [drop()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=drop) | Called when dropping or throwing nil | [pick_up(Entity entity_to_pick_up)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=pick_up) | [Entity](#Entity) | [standing_on()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=standing_on) | @@ -6925,6 +6932,9 @@ bool | [collect_treasure(int value, ENT_TYPE treasure)](https://github.com/spelu bool | [can_jump()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=can_jump) | Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. bool | [is_on_fire()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_on_fire) | bool | [is_powerup_capable()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_powerup_capable) | +bool | [can_be_picked_up_by(Entity entity_picking_up, bool)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=can_be_picked_up_by) | +bool | [can_break_block(bool horizontal, Entity block)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=can_break_block) | +nil | [break_block(bool camera_shake, Entity block)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=break_block) | bool | [damage(Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=damage) | Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer vector<int> | [get_all_behaviors()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_all_behaviors) | Get all available behavior ids bool | [set_behavior(int behavior_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_behavior) | Set behavior, this is more than just state as it's an active function, for example climbing ladder is a behavior and it doesn't actually need ladder/rope entity
Returns false if entity doesn't have this behavior id @@ -6933,6 +6943,13 @@ nil | [set_gravity(float gravity)](https://github.com/spelunky-fyi/overlunky/sea nil | [reset_gravity()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=reset_gravity) | Remove the gravity hook and reset to defaults nil | [set_position(float to_x, float to_y)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_position) | Set the absolute position of an entity and offset all rendering related things accordingly to teleport without any interpolation or graphical glitches. If the camera is focused on the entity, it is also moved. nil | [process_input()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=process_input) | +float | [calculate_jump_velocity(bool dont_ignore_liquid)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=calculate_jump_velocity) | +nil | [apply_velocity(Vec2 velocities, bool ignore_weight)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apply_velocity) | +int | [get_damage()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_damage) | Returns the damage that the entity deals +bool | [attack(Entity victim)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=attack) | Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) +bool | [thrown_into(Entity victim)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=thrown_into) | Same as above, but for being thrown into something and potentially dealing damage that way +int | [get_damage_sound(DAMAGE_TYPE damage)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_damage_sound) | returns sound id for the damage taken, return 0 to make it silence +nil | [copy_extra_info(Entity clone, int some_entity_uid)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=copy_extra_info) | Entities must be of the same type! [CutsceneBehavior](#CutsceneBehavior) | [cutscene](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=cutscene) | nil | [clear_cutscene()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_cutscene) | [VanillaMovableBehavior](#VanillaMovableBehavior) | [get_base_behavior(int state_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_base_behavior) | Gets a vanilla behavior from this movable, needs to be called before `clear_behaviors`
but the returned values are still valid after a call to `clear_behaviors` @@ -6961,6 +6978,10 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_get_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_damage) | Hooks after the virtual function.
The callback signature is `nil get_damage(Movable self)`
Virtual function docs:
Returns the damage that the entity deals [CallbackId](#Aliases) | [set_pre_is_on_fire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_is_on_fire) | Hooks before the virtual function.
The callback signature is `optional is_on_fire(Movable self)` [CallbackId](#Aliases) | [set_post_is_on_fire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_is_on_fire) | Hooks after the virtual function.
The callback signature is `nil is_on_fire(Movable self)` +[CallbackId](#Aliases) | [set_pre_attack(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_attack) | Hooks before the virtual function.
The callback signature is `optional attack(Movable self, Entity victim)`
Virtual function docs:
Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) +[CallbackId](#Aliases) | [set_post_attack(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_attack) | Hooks after the virtual function.
The callback signature is `nil attack(Movable self, Entity victim)`
Virtual function docs:
Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) +[CallbackId](#Aliases) | [set_pre_thrown_into(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_thrown_into) | Hooks before the virtual function.
The callback signature is `optional thrown_into(Movable self, Entity victim)`
Virtual function docs:
Same as above, but for being thrown into something and potentially dealing damage that way +[CallbackId](#Aliases) | [set_post_thrown_into(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_thrown_into) | Hooks after the virtual function.
The callback signature is `nil thrown_into(Movable self, Entity victim)`
Virtual function docs:
Same as above, but for being thrown into something and potentially dealing damage that way [CallbackId](#Aliases) | [set_pre_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_damage) | Hooks before the virtual function.
The callback signature is `optional damage(Movable self, Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer [CallbackId](#Aliases) | [set_post_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_damage) | Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer [CallbackId](#Aliases) | [set_pre_on_hit(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_on_hit) | Hooks before the virtual function.
The callback signature is `bool on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. @@ -6975,40 +6996,54 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_light_on_fire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_light_on_fire) | Hooks after the virtual function.
The callback signature is `nil light_on_fire(Movable self, int time)`
Virtual function docs:
Does not damage entity [CallbackId](#Aliases) | [set_pre_set_cursed(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_set_cursed) | Hooks before the virtual function.
The callback signature is `bool set_cursed(Movable self, bool b, bool effect)` [CallbackId](#Aliases) | [set_post_set_cursed(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_set_cursed) | Hooks after the virtual function.
The callback signature is `nil set_cursed(Movable self, bool b, bool effect)` -[CallbackId](#Aliases) | [set_pre_web_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_web_collision) | Hooks before the virtual function.
The callback signature is `bool web_collision(Movable self)` -[CallbackId](#Aliases) | [set_post_web_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_web_collision) | Hooks after the virtual function.
The callback signature is `nil web_collision(Movable self)` +[CallbackId](#Aliases) | [set_pre_web_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_web_collision) | Hooks before the virtual function.
The callback signature is `bool web_collision(Movable self, bool bool)` +[CallbackId](#Aliases) | [set_post_web_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_web_collision) | Hooks after the virtual function.
The callback signature is `nil web_collision(Movable self, bool bool)` [CallbackId](#Aliases) | [set_pre_check_out_of_bounds(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_check_out_of_bounds) | Hooks before the virtual function.
The callback signature is `bool check_out_of_bounds(Movable self)`
Virtual function docs:
Disable to not get killed outside level bounds. [CallbackId](#Aliases) | [set_post_check_out_of_bounds(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_check_out_of_bounds) | Hooks after the virtual function.
The callback signature is `nil check_out_of_bounds(Movable self)`
Virtual function docs:
Disable to not get killed outside level bounds. [CallbackId](#Aliases) | [set_pre_set_standing_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_set_standing_on) | Hooks before the virtual function.
The callback signature is `bool set_standing_on(Movable self, int entity_uid)` [CallbackId](#Aliases) | [set_post_set_standing_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_set_standing_on) | Hooks after the virtual function.
The callback signature is `nil set_standing_on(Movable self, int entity_uid)` [CallbackId](#Aliases) | [set_pre_standing_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_standing_on) | Hooks before the virtual function.
The callback signature is `optional standing_on(Movable self)` [CallbackId](#Aliases) | [set_post_standing_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_standing_on) | Hooks after the virtual function.
The callback signature is `nil standing_on(Movable self)` -[CallbackId](#Aliases) | [set_pre_stomped_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stomped_by) | Hooks before the virtual function.
The callback signature is `bool stomped_by(Movable self, Entity)` -[CallbackId](#Aliases) | [set_post_stomped_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stomped_by) | Hooks after the virtual function.
The callback signature is `nil stomped_by(Movable self, Entity)` -[CallbackId](#Aliases) | [set_pre_thrown_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_thrown_by) | Hooks before the virtual function.
The callback signature is `bool thrown_by(Movable self, Entity)` -[CallbackId](#Aliases) | [set_post_thrown_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_thrown_by) | Hooks after the virtual function.
The callback signature is `nil thrown_by(Movable self, Entity)` -[CallbackId](#Aliases) | [set_pre_cloned_to(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_cloned_to) | Hooks before the virtual function.
The callback signature is `bool cloned_to(Movable self, Entity)` -[CallbackId](#Aliases) | [set_post_cloned_to(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_cloned_to) | Hooks after the virtual function.
The callback signature is `nil cloned_to(Movable self, Entity)` +[CallbackId](#Aliases) | [set_pre_stomped_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stomped_by) | Hooks before the virtual function.
The callback signature is `optional stomped_by(Movable self, Entity stomper)` +[CallbackId](#Aliases) | [set_post_stomped_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stomped_by) | Hooks after the virtual function.
The callback signature is `nil stomped_by(Movable self, Entity stomper)` +[CallbackId](#Aliases) | [set_pre_thrown_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_thrown_by) | Hooks before the virtual function.
The callback signature is `bool thrown_by(Movable self, Entity thrower)` +[CallbackId](#Aliases) | [set_post_thrown_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_thrown_by) | Hooks after the virtual function.
The callback signature is `nil thrown_by(Movable self, Entity thrower)` +[CallbackId](#Aliases) | [set_pre_cloned_to(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_cloned_to) | Hooks before the virtual function.
The callback signature is `bool cloned_to(Movable self, Entity clone int some_entity_uid)` +[CallbackId](#Aliases) | [set_post_cloned_to(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_cloned_to) | Hooks after the virtual function.
The callback signature is `nil cloned_to(Movable self, Entity clone int some_entity_uid)` [CallbackId](#Aliases) | [set_pre_pick_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_pick_up) | Hooks before the virtual function.
The callback signature is `bool pick_up(Movable self, Entity entity_to_pick_up)` [CallbackId](#Aliases) | [set_post_pick_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_pick_up) | Hooks after the virtual function.
The callback signature is `nil pick_up(Movable self, Entity entity_to_pick_up)` -[CallbackId](#Aliases) | [set_pre_picked_up_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_picked_up_by) | Hooks before the virtual function.
The callback signature is `bool picked_up_by(Movable self, Entity)` -[CallbackId](#Aliases) | [set_post_picked_up_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_picked_up_by) | Hooks after the virtual function.
The callback signature is `nil picked_up_by(Movable self, Entity)` +[CallbackId](#Aliases) | [set_pre_can_be_picked_up_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_can_be_picked_up_by) | Hooks before the virtual function.
The callback signature is `optional can_be_picked_up_by(Movable self, Entity entity_picking_up, bool)` +[CallbackId](#Aliases) | [set_post_can_be_picked_up_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_can_be_picked_up_by) | Hooks after the virtual function.
The callback signature is `nil can_be_picked_up_by(Movable self, Entity entity_picking_up, bool)` [CallbackId](#Aliases) | [set_pre_drop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_drop) | Hooks before the virtual function.
The callback signature is `bool drop(Movable self)`
Virtual function docs:
Called when dropping or throwing [CallbackId](#Aliases) | [set_post_drop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_drop) | Hooks after the virtual function.
The callback signature is `nil drop(Movable self)`
Virtual function docs:
Called when dropping or throwing [CallbackId](#Aliases) | [set_pre_collect_treasure(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_collect_treasure) | Hooks before the virtual function.
The callback signature is `optional collect_treasure(Movable self, int value, ENT_TYPE treasure)`
Virtual function docs:
Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. [CallbackId](#Aliases) | [set_post_collect_treasure(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_collect_treasure) | Hooks after the virtual function.
The callback signature is `nil collect_treasure(Movable self, int value, ENT_TYPE treasure)`
Virtual function docs:
Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. +[CallbackId](#Aliases) | [set_pre_apply_movement(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_apply_movement) | Hooks before the virtual function.
The callback signature is `optional apply_movement(Movable self, int, int, int)` +[CallbackId](#Aliases) | [set_post_apply_movement(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_apply_movement) | Hooks after the virtual function.
The callback signature is `nil apply_movement(Movable self, int, int, int)` +[CallbackId](#Aliases) | [set_pre_is_powerup_capable(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_is_powerup_capable) | Hooks before the virtual function.
The callback signature is `optional is_powerup_capable(Movable self)` +[CallbackId](#Aliases) | [set_post_is_powerup_capable(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_is_powerup_capable) | Hooks after the virtual function.
The callback signature is `nil is_powerup_capable(Movable self)` [CallbackId](#Aliases) | [set_pre_initialize(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_initialize) | Hooks before the virtual function.
The callback signature is `bool initialize(Movable self)` [CallbackId](#Aliases) | [set_post_initialize(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_initialize) | Hooks after the virtual function.
The callback signature is `nil initialize(Movable self)` [CallbackId](#Aliases) | [set_pre_process_input(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_process_input) | Hooks before the virtual function.
The callback signature is `bool process_input(Movable self)` [CallbackId](#Aliases) | [set_post_process_input(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_process_input) | Hooks after the virtual function.
The callback signature is `nil process_input(Movable self)` [CallbackId](#Aliases) | [set_pre_picked_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_picked_up) | Hooks before the virtual function.
The callback signature is `bool picked_up(Movable self)` [CallbackId](#Aliases) | [set_post_picked_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_picked_up) | Hooks after the virtual function.
The callback signature is `nil picked_up(Movable self)` -[CallbackId](#Aliases) | [set_pre_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_fall) | Hooks before the virtual function.
The callback signature is `bool fall(Movable self)` -[CallbackId](#Aliases) | [set_post_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_fall) | Hooks after the virtual function.
The callback signature is `nil fall(Movable self)` +[CallbackId](#Aliases) | [set_pre_release(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_release) | Hooks before the virtual function.
The callback signature is `bool release(Movable self)` +[CallbackId](#Aliases) | [set_post_release(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_release) | Hooks after the virtual function.
The callback signature is `nil release(Movable self)` +[CallbackId](#Aliases) | [set_pre_generate_fall_poof_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_generate_fall_poof_particles) | Hooks before the virtual function.
The callback signature is `bool generate_fall_poof_particles(Movable self)` +[CallbackId](#Aliases) | [set_post_generate_fall_poof_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_generate_fall_poof_particles) | Hooks after the virtual function.
The callback signature is `nil generate_fall_poof_particles(Movable self)` +[CallbackId](#Aliases) | [set_pre_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_fall) | Hooks before the virtual function.
The callback signature is `bool fall(Movable self, float float)` +[CallbackId](#Aliases) | [set_post_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_fall) | Hooks after the virtual function.
The callback signature is `nil fall(Movable self, float float)` [CallbackId](#Aliases) | [set_pre_apply_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_apply_friction) | Hooks before the virtual function.
The callback signature is `bool apply_friction(Movable self, float, bool vertical, float)` [CallbackId](#Aliases) | [set_post_apply_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_apply_friction) | Hooks after the virtual function.
The callback signature is `nil apply_friction(Movable self, float, bool vertical, float)` -[CallbackId](#Aliases) | [set_pre_crush(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_crush) | Hooks before the virtual function.
The callback signature is `bool crush(Movable self, Entity)` -[CallbackId](#Aliases) | [set_post_crush(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_crush) | Hooks after the virtual function.
The callback signature is `nil crush(Movable self, Entity)` +[CallbackId](#Aliases) | [set_pre_can_break_block(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_can_break_block) | Hooks before the virtual function.
The callback signature is `optional can_break_block(Movable self, bool horizontal, Entity block)` +[CallbackId](#Aliases) | [set_post_can_break_block(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_can_break_block) | Hooks after the virtual function.
The callback signature is `nil can_break_block(Movable self, bool horizontal, Entity block)` +[CallbackId](#Aliases) | [set_pre_break_block(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_break_block) | Hooks before the virtual function.
The callback signature is `bool break_block(Movable self, bool camera_shake, Entity block)` +[CallbackId](#Aliases) | [set_post_break_block(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_break_block) | Hooks after the virtual function.
The callback signature is `nil break_block(Movable self, bool camera_shake, Entity block)` +[CallbackId](#Aliases) | [set_pre_crush(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_crush) | Hooks before the virtual function.
The callback signature is `bool crush(Movable self, Entity entity)` +[CallbackId](#Aliases) | [set_post_crush(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_crush) | Hooks after the virtual function.
The callback signature is `nil crush(Movable self, Entity entity)` +[CallbackId](#Aliases) | [set_pre_instakill_death(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_instakill_death) | Hooks before the virtual function.
The callback signature is `bool instakill_death(Movable self)` +[CallbackId](#Aliases) | [set_post_instakill_death(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_instakill_death) | Hooks after the virtual function.
The callback signature is `nil instakill_death(Movable self)` ### MovingIcon diff --git a/src/game_api/entity.hpp b/src/game_api/entity.hpp index ab21a4815..268e3624f 100644 --- a/src/game_api/entity.hpp +++ b/src/game_api/entity.hpp @@ -222,7 +222,7 @@ class Entity { clear_dtor_impl(this, dtor_cb_id); } - + /// NoDoc void set_enable_turning(bool enabled); std::vector get_items(); diff --git a/src/game_api/entity_db.hpp b/src/game_api/entity_db.hpp index cb1c47202..0b2f2b848 100644 --- a/src/game_api/entity_db.hpp +++ b/src/game_api/entity_db.hpp @@ -40,7 +40,7 @@ struct EntityDB float width; float height; uint8_t draw_depth; - uint8_t default_b3f; // value gets copied into entity.b3f along with draw_depth etc (RVA 0x21F30CC4) + uint8_t default_b3f; // value gets copied into entity.b3f along with draw_depth etc int16_t field_26; union { @@ -148,7 +148,6 @@ struct EntityFactory bool type_set[0x395]; std::unordered_map> entity_instance_map; // game_unorderedmap probably EntityMap entity_map; // game_unorderedmap probably - void* _ptr_7; }; EntityDB* get_type(uint32_t id); diff --git a/src/game_api/movable.hpp b/src/game_api/movable.hpp index 312420b81..b6e1b86bf 100644 --- a/src/game_api/movable.hpp +++ b/src/game_api/movable.hpp @@ -127,11 +127,6 @@ class Movable : public Entity /// Remove the gravity hook and reset to defaults void reset_gravity(); - // don't use this, it's only to not break backwards compatibility - void light_on_fire_broken() - { - this->light_on_fire(0x64); // kind of standard value that the game uses - } /// Get all available behavior ids std::vector get_all_behaviors(); /// Set behavior, this is more than just state as it's an active function, for example climbing ladder is a behavior and it doesn't actually need ladder/rope entity @@ -143,20 +138,6 @@ class Movable : public Entity /// Set the absolute position of an entity and offset all rendering related things accordingly to teleport without any interpolation or graphical glitches. If the camera is focused on the entity, it is also moved. void set_position(float to_x, float to_y); - // for backwards compatibility - // adds a coin to the table cause the collected_money_count is expected to increase - void add_money_broken(int amount) - { - static const auto coin = to_id("ENT_TYPE_ITEM_GOLDCOIN"); - this->collect_treasure(amount, coin); - } - - /// effect = true - plays the sound and spawn particle above entity - void set_cursed_fix(bool b, std::optional effect) - { - set_cursed(b, effect.value_or(true)); - } - /// Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. virtual bool can_jump() = 0; // 37 virtual void get_collision_info(CollisionInfo& dest) = 0; // 38, from entityDB @@ -194,7 +175,7 @@ class Movable : public Entity /// Disable to not get killed outside level bounds. virtual void check_out_of_bounds() = 0; // 58, kills with the 'still falling' death cause, is called for any item/fx/mount/monster/player virtual void set_standing_on(int32_t entity_uid) = 0; // 59 - virtual Entity* standing_on() = 0; // 60, looks up movable.standing_on_uid in state.instance_id_to_pointer + virtual Entity* standing_on() = 0; // 60 virtual bool on_stomped_on_by(Entity* stomper) = 0; // 61 virtual void on_thrown_by(Entity* thrower) = 0; // 62, implemented for special cases like hired hand (player with ai_func), horned lizard... /// Entities must be of the same type! diff --git a/src/game_api/script/usertypes/entity_lua.cpp b/src/game_api/script/usertypes/entity_lua.cpp index e82f75b94..9c71924ad 100644 --- a/src/game_api/script/usertypes/entity_lua.cpp +++ b/src/game_api/script/usertypes/entity_lua.cpp @@ -49,13 +49,18 @@ void register_usertypes(sol::state& lua) entitydb_type["search_flags"] = &EntityDB::search_flags; entitydb_type["width"] = &EntityDB::width; entitydb_type["height"] = &EntityDB::height; + entitydb_type["draw_depth"] = &EntityDB::draw_depth; entitydb_type["offsetx"] = &EntityDB::default_offsetx; entitydb_type["offsety"] = &EntityDB::default_offsety; entitydb_type["hitboxx"] = &EntityDB::default_hitboxx; entitydb_type["hitboxy"] = &EntityDB::default_hitboxy; - entitydb_type["draw_depth"] = &EntityDB::draw_depth; + entitydb_type["default_shape"] = &EntityDB::default_shape; + entitydb_type["default_hitbox_enabled"] = &EntityDB::default_hitbox_enabled; entitydb_type["collision2_mask"] = &EntityDB::collision2_mask; entitydb_type["collision_mask"] = &EntityDB::collision_mask; + entitydb_type["default_flags"] = &EntityDB::default_flags; + entitydb_type["default_more_flags"] = &EntityDB::default_more_flags; + entitydb_type["properties_flags"] = &EntityDB::properties_flags; entitydb_type["friction"] = &EntityDB::friction; entitydb_type["elasticity"] = &EntityDB::elasticity; entitydb_type["weight"] = &EntityDB::weight; @@ -68,21 +73,20 @@ void register_usertypes(sol::state& lua) entitydb_type["glow_green"] = &EntityDB::glow_green; entitydb_type["glow_blue"] = &EntityDB::glow_blue; entitydb_type["glow_alpha"] = &EntityDB::glow_alpha; + entitydb_type["texture"] = &EntityDB::texture_id; + entitydb_type["tilex"] = &EntityDB::tile_x; + entitydb_type["tiley"] = &EntityDB::tile_y; entitydb_type["damage"] = &EntityDB::damage; entitydb_type["life"] = &EntityDB::life; entitydb_type["sacrifice_value"] = &EntityDB::sacrifice_value; entitydb_type["blood_content"] = &EntityDB::blood_content; - entitydb_type["texture"] = &EntityDB::texture_id; - entitydb_type["animations"] = &EntityDB::animations; - entitydb_type["properties_flags"] = &EntityDB::properties_flags; - entitydb_type["default_flags"] = &EntityDB::default_flags; - entitydb_type["default_more_flags"] = &EntityDB::default_more_flags; entitydb_type["leaves_corpse_behind"] = &EntityDB::leaves_corpse_behind; + entitydb_type["description"] = &EntityDB::description; entitydb_type["sound_killed_by_player"] = &EntityDB::sound_killed_by_player; entitydb_type["sound_killed_by_other"] = &EntityDB::sound_killed_by_other; - entitydb_type["description"] = &EntityDB::description; - entitydb_type["tilex"] = &EntityDB::tile_x; - entitydb_type["tiley"] = &EntityDB::tile_y; + entitydb_type["animations"] = &EntityDB::animations; + entitydb_type["default_special_offsetx"] = &EntityDB::default_special_offsetx; + entitydb_type["default_special_offsetx"] = &EntityDB::default_special_offsety; /// Some information used to render the entity, can not be changed, used in Entity lua.new_usertype( @@ -244,6 +248,7 @@ void register_usertypes(sol::state& lua) { ent.set_draw_depth(depth, 0); }); entity_type["set_draw_depth"] = set_draw_depth; + entity_type["reset_draw_depth"] = &Entity::reset_draw_depth; entity_type["set_enable_turning"] = &Entity::set_enable_turning; auto liberate_from_shop = sol::overload(&Entity::liberate_from_shop, [](Entity& ent) // for backward compatibility) @@ -266,11 +271,15 @@ void register_usertypes(sol::state& lua) entity_type["get_items"] = &Entity::get_items; entity_type["is_in_liquid"] = &Entity::is_in_liquid; entity_type["is_cursed"] = &Entity::is_cursed; + entity_type["is_movable"] = &Entity::is_movable; + entity_type["can_be_pushed"] = &Entity::can_be_pushed; entity_type["kill_recursive"] = kill_recursive; entity_type["destroy_recursive"] = destroy_recursive; entity_type["update"] = &Entity::update_state_machine; entity_type["flip"] = &Entity::flip; - entity_type["can_be_pushed"] = &Entity::can_be_pushed; + entity_type["remove_item"] = &Entity::remove_item; + entity_type["apply_db"] = &Entity::apply_db; + /* Entity // user_data // You can put any arbitrary lua object here for custom entities or player stats, which is then saved across level transitions for players and carried items, mounts etc... This field is local to the script and multiple scripts can write different things in the same entity. The data is saved right before ON.PRE_LOAD_SCREEN from a level and loaded right before ON.POST_LOAD_SCREEN to a level or transition. It is not available yet in post_entity_spawn, but that is a good place to initialize it for new custom entities. See example for more. @@ -280,11 +289,15 @@ void register_usertypes(sol::state& lua) &Movable::broken_damage, &Movable::damage); auto light_on_fire = sol::overload( - static_cast(&Movable::light_on_fire_broken), - static_cast(&Movable::light_on_fire)); + [](Movable& ent) // for backwards compatibility + { ent.light_on_fire(0x64); }, // kind of standard value that the game uses + &Movable::light_on_fire); auto add_money = sol::overload( - static_cast(&Movable::add_money_broken), - static_cast(&Movable::collect_treasure)); + [](Movable& ent, int amount) // for backwards compatibility + {static const auto coin = to_id("ENT_TYPE_ITEM_GOLDCOIN"); + ent.collect_treasure(amount, coin); }, // adds a coin to the table cause the collected_money_count is expected to increase + &Movable::collect_treasure); + auto movable_type = lua.new_usertype("Movable", sol::base_classes, sol::bases()); movable_type["move"] = &Movable::move; movable_type["movex"] = &Movable::movex; @@ -293,6 +306,7 @@ void register_usertypes(sol::state& lua) movable_type["buttons_previous"] = &Movable::buttons_previous; movable_type["stand_counter"] = &Movable::stand_counter; movable_type["jump_height_multiplier"] = &Movable::jump_height_multiplier; + movable_type["price"] = &Movable::price; movable_type["owner_uid"] = &Movable::owner_uid; movable_type["last_owner_uid"] = &Movable::last_owner_uid; movable_type["current_animation"] = &Movable::current_animation; @@ -319,7 +333,6 @@ void register_usertypes(sol::state& lua) movable_type["exit_invincibility_timer"] = &Movable::exit_invincibility_timer; movable_type["invincibility_frames_timer"] = &Movable::invincibility_frames_timer; movable_type["frozen_timer"] = &Movable::frozen_timer; - movable_type["price"] = &Movable::price; movable_type["is_poisoned"] = &Movable::is_poisoned; movable_type["poison"] = &Movable::poison; movable_type["is_button_pressed"] = &Movable::is_button_pressed; @@ -327,12 +340,15 @@ void register_usertypes(sol::state& lua) movable_type["is_button_released"] = &Movable::is_button_released; movable_type["stun"] = &Movable::stun; - auto freeze = sol::overload(&Movable::freeze, [](Movable& ent, uint8_t frame_count) // for backward compatibility + auto freeze = sol::overload(&Movable::freeze, [](Movable& ent, uint8_t frame_count) // for backwards compatibility { ent.freeze(frame_count, false); }); + auto set_cursed = sol::overload(&Movable::set_cursed, [](Movable& ent, bool b) // for backwards compatibility + { ent.set_cursed(b, true); }); + movable_type["freeze"] = freeze; movable_type["light_on_fire"] = light_on_fire; - movable_type["set_cursed"] = &Movable::set_cursed_fix; + movable_type["set_cursed"] = set_cursed; movable_type["drop"] = &Movable::drop; movable_type["pick_up"] = &Movable::pick_up; movable_type["standing_on"] = &Movable::standing_on; @@ -342,6 +358,9 @@ void register_usertypes(sol::state& lua) movable_type["can_jump"] = &Movable::can_jump; movable_type["is_on_fire"] = &Movable::is_on_fire; movable_type["is_powerup_capable"] = &Movable::is_powerup_capable; + movable_type["can_be_picked_up_by"] = &Movable::can_be_picked_up_by; + movable_type["can_break_block"] = &Movable::can_break_block; + movable_type["break_block"] = &Movable::break_block; movable_type["damage"] = damage; movable_type["get_all_behaviors"] = &Movable::get_all_behaviors; movable_type["set_behavior"] = &Movable::set_behavior; @@ -350,6 +369,13 @@ void register_usertypes(sol::state& lua) movable_type["reset_gravity"] = &Movable::reset_gravity; movable_type["set_position"] = &Movable::set_position; movable_type["process_input"] = &Movable::process_input; + movable_type["calculate_jump_velocity"] = &Movable::calculate_jump_velocity; + movable_type["apply_velocity"] = &Movable::apply_velocity; + movable_type["get_damage"] = &Movable::get_damage; + movable_type["attack"] = &Movable::attack; + movable_type["thrown_into"] = &Movable::thrown_into; + movable_type["get_damage_sound"] = &Movable::get_damage_sound; + movable_type["copy_extra_info"] = &Movable::copy_extra_info; movable_type["cutscene"] = sol::readonly(&Movable::cutscene_behavior); movable_type["clear_cutscene"] = [](Movable& movable) -> void { diff --git a/src/game_api/script/usertypes/vtables_lua.cpp b/src/game_api/script/usertypes/vtables_lua.cpp index f83daa5ce..a775883ce 100644 --- a/src/game_api/script/usertypes/vtables_lua.cpp +++ b/src/game_api/script/usertypes/vtables_lua.cpp @@ -67,31 +67,42 @@ void register_usertypes(sol::state& lua) /// NoDoc VTableEntry<"stomp_damage", 43, MemFun<&Movable::get_damage>>, VTableEntry<"get_damage", 43, MemFun<&Movable::get_damage>>, - VTableEntry<"is_on_fire", 45, bool()>, - VTableEntry<"damage", 48, bool(Entity*, int8_t, uint16_t, Vec2*, uint8_t, uint16_t, uint8_t, bool)>, - VTableEntry<"on_hit", 49, void(Entity*)>, - VTableEntry<"get_damage_sound", 50, uint32_t(DAMAGE_TYPE)>, - VTableEntry<"stun", 51, void(uint16_t)>, - VTableEntry<"freeze", 52, void(uint8_t)>, - VTableEntry<"light_on_fire", 53, void(uint8_t)>, - VTableEntry<"set_cursed", 54, void(bool)>, - VTableEntry<"web_collision", 55, void()>, - VTableEntry<"check_out_of_bounds", 58, void()>, - VTableEntry<"set_standing_on", 59, void(int32_t)>, - VTableEntry<"standing_on", 60, Entity*()>, - VTableEntry<"stomped_by", 61, void(Entity*)>, - VTableEntry<"thrown_by", 62, void(Entity*)>, - VTableEntry<"cloned_to", 63, void(Entity*)>, - VTableEntry<"pick_up", 67, void(Entity*)>, - VTableEntry<"picked_up_by", 68, void(Entity*)>, - VTableEntry<"drop", 69, void(Entity*)>, - VTableEntry<"collect_treasure", 70, void(int32_t, uint32_t)>, - VTableEntry<"initialize", 75, void()>, - VTableEntry<"process_input", 78, void()>, - VTableEntry<"picked_up", 80, void()>, - VTableEntry<"fall", 83, void()>, - VTableEntry<"apply_friction", 84, void()>, - VTableEntry<"crush", 90, void(Entity*)>>; + VTableEntry<"is_on_fire", 45, MemFun<&Movable::is_on_fire>>, + VTableEntry<"attack", 46, MemFun<&Movable::attack>>, + VTableEntry<"thrown_into", 47, MemFun<&Movable::thrown_into>>, + VTableEntry<"damage", 48, MemFun<&Movable::damage>>, + VTableEntry<"on_hit", 49, MemFun<&Movable::on_hit>>, + VTableEntry<"get_damage_sound", 50, MemFun<&Movable::get_damage_sound>>, + VTableEntry<"stun", 51, MemFun<&Movable::stun>>, + VTableEntry<"freeze", 52, MemFun<&Movable::freeze>>, + VTableEntry<"light_on_fire", 53, MemFun<&Movable::light_on_fire>>, + VTableEntry<"set_cursed", 54, MemFun<&Movable::set_cursed>>, + VTableEntry<"web_collision", 55, MemFun<&Movable::on_spiderweb_collision>>, + VTableEntry<"check_out_of_bounds", 58, MemFun<&Movable::check_out_of_bounds>>, + VTableEntry<"set_standing_on", 59, MemFun<&Movable::set_standing_on>>, + VTableEntry<"standing_on", 60, MemFun<&Movable::standing_on>>, + VTableEntry<"stomped_by", 61, MemFun<&Movable::on_stomped_on_by>>, + VTableEntry<"thrown_by", 62, MemFun<&Movable::on_thrown_by>>, + VTableEntry<"cloned_to", 63, MemFun<&Movable::copy_extra_info>>, + VTableEntry<"pick_up", 67, MemFun<&Movable::pick_up>>, + /// NoDoc + VTableEntry<"picked_up_by", 68, MemFun<&Movable::can_be_picked_up_by>>, + VTableEntry<"can_be_picked_up_by", 68, MemFun<&Movable::can_be_picked_up_by>>, + VTableEntry<"drop", 69, MemFun<&Movable::drop>>, + VTableEntry<"collect_treasure", 70, MemFun<&Movable::collect_treasure>>, + VTableEntry<"apply_movement", 71, MemFun<&Movable::apply_movement>>, + VTableEntry<"is_powerup_capable", 74, MemFun<&Movable::is_powerup_capable>>, + VTableEntry<"initialize", 75, MemFun<&Movable::initialize>>, + VTableEntry<"process_input", 78, MemFun<&Movable::process_input>>, + VTableEntry<"picked_up", 80, MemFun<&Movable::on_picked_up>>, + VTableEntry<"release", 81, MemFun<&Movable::on_release>>, + VTableEntry<"generate_fall_poof_particles", 82, MemFun<&Movable::generate_fall_poof_particles>>, + VTableEntry<"fall", 83, MemFun<&Movable::handle_fall_logic>>, + VTableEntry<"apply_friction", 84, MemFun<&Movable::apply_friction>>, + VTableEntry<"can_break_block", 85, MemFun<&Movable::can_break_block>>, + VTableEntry<"break_block", 86, MemFun<&Movable::break_block>>, + VTableEntry<"crush", 90, MemFun<&Movable::on_crushed_by>>, + VTableEntry<"instakill_death", 92, MemFun<&Movable::on_instakill_death>>>; static MovableVTable movable_vtable(lua, lua["Movable"], "ENTITY_OVERRIDE"); using FloorVTable = HookableVTable< From 8c1a6916bbe0f668ef1bcb52d669cd78706dcc49 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Mon, 23 Sep 2024 12:52:29 +0200 Subject: [PATCH 09/21] add SOUNDID alias, add function to convert from it to `VANILLA_SOUND` and vice versa. Some comments fix, clean up Entity file a little,expose some more stuff --- docs/game_data/spel2.lua | 79 +++++++-- docs/src/includes/_enums.md | 4 +- docs/src/includes/_events.md | 4 +- docs/src/includes/_globals.md | 30 +++- docs/src/includes/_home.md | 1 + docs/src/includes/_types.md | 53 ++++-- src/game_api/aliases.hpp | 1 + src/game_api/entities_activefloors.cpp | 2 +- src/game_api/entities_chars.hpp | 2 +- src/game_api/entities_floors.cpp | 2 +- src/game_api/entities_floors.hpp | 2 +- src/game_api/entities_items.hpp | 23 ++- src/game_api/entities_monsters.hpp | 2 +- src/game_api/entities_mounts.hpp | 32 ++-- src/game_api/entity.cpp | 163 ++++-------------- src/game_api/entity.hpp | 78 ++++----- src/game_api/entity_db.cpp | 23 +-- src/game_api/entity_db.hpp | 16 +- src/game_api/entity_lookup.cpp | 2 +- src/game_api/layer.cpp | 4 +- src/game_api/movable.hpp | 2 +- src/game_api/rpc.cpp | 40 ++++- src/game_api/script/lua_vm.cpp | 54 ++++-- .../script/usertypes/entities_items_lua.cpp | 14 ++ .../usertypes/entities_monsters_lua.cpp | 12 ++ .../script/usertypes/entities_mounts_lua.cpp | 14 ++ src/game_api/script/usertypes/entity_lua.cpp | 12 +- src/game_api/script/usertypes/hitbox_lua.cpp | 14 +- src/game_api/script/usertypes/sound_lua.cpp | 27 ++- src/game_api/search.cpp | 5 +- src/game_api/sound_manager.cpp | 74 ++++---- src/game_api/sound_manager.hpp | 19 +- src/game_api/spawn_api.cpp | 4 +- src/game_api/state.cpp | 2 +- src/injected/ui.cpp | 34 ++-- src/injected/ui_util.cpp | 68 +++++++- src/injected/ui_util.hpp | 1 + 37 files changed, 550 insertions(+), 369 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index b666426e2..879ca2188 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -535,7 +535,7 @@ function set_contents(uid, item_entity_type) end ---@return Entity function get_entity(uid) end ---Get the [EntityDB](https://spelunky-fyi.github.io/overlunky/#EntityDB) behind an ENT_TYPE... ----@param id integer +---@param id ENT_TYPE ---@return EntityDB function get_type(id) end ---Gets a grid entity, such as floor or spikes, at the given position and layer. @@ -670,7 +670,7 @@ function get_position(uid) end ---@param uid integer ---@return number, number, integer function get_render_position(uid) end ----Get velocity `vx, vy` of an entity by uid. Use this, don't use `Entity.velocityx/velocityy` because those are relative to `Entity.overlay`. +---Get velocity `vx, vy` of an entity by uid. Use this to get velocity relative to the game world, (the `Entity.velocityx/velocityy` are relative to `Entity.overlay`). Only works for movable or liquid entities ---@param uid integer ---@return number, number function get_velocity(uid) end @@ -998,12 +998,12 @@ function raise() end ---@param hash integer ---@return STRINGID function hash_to_stringid(hash) end ----Get string behind STRINGID, don't use stringid directly for vanilla string, use [hash_to_stringid](https://spelunky-fyi.github.io/overlunky/#hash_to_stringid) first +---Get string behind STRINGID, **don't use stringid directly for vanilla string**, use [hash_to_stringid](https://spelunky-fyi.github.io/overlunky/#hash_to_stringid) first ---Will return the string of currently choosen language ---@param string_id STRINGID ---@return string function get_string(string_id) end ----Change string at the given id (don't use stringid diretcly for vanilla string, use `hash_to_stringid` first) +---Change string at the given id (**don't use stringid directly for vanilla string**, use [hash_to_stringid](https://spelunky-fyi.github.io/overlunky/#hash_to_stringid) first) ---This edits custom string and in game strings but changing the language in settings will reset game strings ---@param id STRINGID ---@param str string @@ -1046,7 +1046,7 @@ function change_sunchallenge_spawns(ent_types) end ---ENT_TYPE_ITEM_PICKUP_SPIKESHOES, ENT_TYPE_ITEM_PICKUP_SPRINGSHOES, ITEM_MACHETE, ITEM_BOOMERANG, ITEM_CROSSBOW, ITEM_SHOTGUN, ITEM_FREEZERAY, ITEM_WEBGUN, ITEM_CAMERA, ITEM_MATTOCK, ITEM_PURCHASABLE_JETPACK, ITEM_PURCHASABLE_HOVERPACK, ---ITEM_TELEPORTER, ITEM_PURCHASABLE_TELEPORTER_BACKPACK, ITEM_PURCHASABLE_POWERPACK} ---Min 6, Max 255, if you want less then 6 you need to write some of them more then once (they will have higher "spawn chance"). ----If you use this function in the level with diceshop in it, you have to update `item_ids` in the [ITEM_DICE_PRIZE_DISPENSER](https://spelunky-fyi.github.io/overlunky/#PrizeDispenser). +---If you use this function in the level with dice shop in it, you have to update `item_ids` in the [ITEM_DICE_PRIZE_DISPENSER](https://spelunky-fyi.github.io/overlunky/#PrizeDispenser). ---Use empty table as argument to reset to the game default ---@param ent_types ENT_TYPE[] ---@return nil @@ -1368,7 +1368,7 @@ function set_infinite_loop_detection_enabled(enable) end ---@param enable boolean ---@return nil function set_camera_layer_control_enabled(enable) end ----Set multiplier (default 1.0) for a QueryPerformanceCounter hook based speedhack, similar to the one in Cheat Engine. Call without arguments to reset. Also see set_frametime +---Set multiplier (default 1.0) for a QueryPerformanceCounter hook based speedhack, similar to the one in Cheat Engine. Call without arguments to reset. Also see [set_frametime](https://spelunky-fyi.github.io/overlunky/#set_frametime) ---@param multiplier number? ---@return nil function set_speedhack(multiplier) end @@ -1384,7 +1384,7 @@ function get_performance_frequency() end ---Initializes some adventure run related values and loads the character select screen, as if starting a new adventure run from the Play menu. Character select can be skipped by changing `state.screen_next` right after calling this function, maybe with `warp()`. If player isn't already selected, make sure to set `state.items.player_select` and `state.items.player_count` appropriately too. ---@return nil function play_adventure() end ----Initializes some seedeed run related values and loads the character select screen, as if starting a new seeded run after entering the seed. +---Initializes some seeded run related values and loads the character select screen, as if starting a new seeded run after entering the seed. ---@param seed integer? ---@return nil function play_seeded(seed) end @@ -1695,10 +1695,25 @@ function set_vanilla_sound_callback(name, types, cb) end ---@param id CallbackId ---@return nil function clear_vanilla_sound_callback(id) end +---Use source_uid to make the sound be played at the location of that entity, set it -1 to just play it "everywhere" +---Returns SoundMeta, beware that the sound can't be stopped (`start_over` and `playing` are unavailable). Should only be used for sfx. ---@param sound VANILLA_SOUND ---@param source_uid integer ---@return SoundMeta function play_sound(sound, source_uid) end +---Use source_uid to make the sound be played at the location of that entity, set it -1 to just play it "everywhere" +---Returns SoundMeta, beware that the sound can't be stopped (`start_over` and `playing` are unavailable). Should only be used for sfx. +---@param sound_id SOUNDID +---@param source_uid integer +---@return SoundMeta +function play_sound(sound_id, source_uid) end +---@param id SOUNDID +---@return VANILLA_SOUND +function convert_sound_id(id) end +---Convert SOUNDID to VANILLA_SOUND and vice versa +---@param sound VANILLA_SOUND +---@return SOUNDID +function convert_sound_id(sound) end ---Calculate the bounding box of text, so you can center it etc. Returns `width`, `height` in screen distance. ---@param size number ---@param text string @@ -2427,10 +2442,10 @@ function PRNG:random(min, max) end ---@field width number ---@field height number ---@field draw_depth integer - ---@field offsetx number - ---@field offsety number - ---@field hitboxx number - ---@field hitboxy number + ---@field offsetx number @Offset of the hitbox in relation to the entity position + ---@field offsety number @Offset of the hitbox in relation to the entity position + ---@field hitboxx number @Half of the width of the hitbox + ---@field hitboxy number @Half of the height of the hitbox ---@field default_shape SHAPE ---@field default_hitbox_enabled boolean ---@field collision2_mask integer @MASK, will only call collision2 when colliding with entities that match this mask. @@ -2516,15 +2531,14 @@ function PRNG:random(min, max) end ---@field offsety number @Offset of the hitbox in relation to the entity position ---@field rendering_info RenderInfo ---@field user_data any - ---@field topmost fun(self): Entity - ---@field topmost_mount fun(self): Entity + ---@field topmost fun(self): Entity @Returns the top entity in a chain (overlay) ---@field get_texture fun(self): TEXTURE ---@field set_texture fun(self, texture_id: TEXTURE): boolean @Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one ---@field set_draw_depth fun(self, draw_depth: integer, b3f: integer): nil ---@field reset_draw_depth fun(self): nil ---@field liberate_from_shop fun(self, clear_parrent: boolean): nil @`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 ---@field get_held_entity fun(self): Entity - ---@field set_layer fun(self, layer: LAYER): nil @Moves the entity to specified layer, nothing else happens, so this does not emulate a door transition + ---@field set_layer fun(self, layer: LAYER): nil @Moves the entity to specified layer with all it's items, nothing else happens, so this does not emulate a door transition ---@field apply_layer fun(self): nil @Adds the entity to its own layer, to add it to entity lookup tables without waiting for a state update ---@field remove fun(self): nil @Moves the entity to the limbo-layer where it can later be retrieved from again via `respawn` ---@field respawn fun(self, layer_to: LAYER): nil @Moves the entity from the limbo-layer (where it was previously put by `remove`) to `layer` @@ -2545,6 +2559,8 @@ function PRNG:random(min, max) end ---@field flip fun(self, left: boolean): nil ---@field remove_item fun(self, entity: Entity, autokill_check: boolean): nil ---@field apply_db fun(self): nil @Applies changes made in `entity.type` + ---@field get_absolute_velocity fun(self): Vec2 @Get's the velocity relative to the game world, only for movable or liquid entities + ---@field get_hitbox fun(self, use_render_pos: boolean?): AABB @`use_render_pos` default is `false` ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. @@ -2894,7 +2910,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field get_short_name fun(self): string @Get the short name of the character, this will be the modded name not only the vanilla name. ---@field get_heart_color fun(self): Color @Get the heart color of the character, this will be the modded heart color not only the vanilla heart color. ---@field is_female fun(self): boolean @Check whether the character is female, will be `true` if the character was modded to be female as well. - ---@field set_heart_color fun(self, hcolor: Color): nil @Set the heart color the character. + ---@field set_heart_color fun(self, hcolor: Color): nil @Set the heart color for the character. ---@field let_go fun(self): nil @Drops from ladders, ropes and ledge grabs ---@class Floor : Entity @@ -2972,7 +2988,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@class TotemTrap : Floor ---@field spawn_entity_type ENT_TYPE - ---@field first_sound_id integer + ---@field first_sound_id SOUNDID ---@field trigger fun(self, who_uid: integer, left: boolean): nil @The uid must be movable entity for ownership transfers ---@class LaserTrap : Floor @@ -3174,6 +3190,13 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field remove_rider fun(self): nil ---@field carry fun(self, rider: Movable): nil ---@field tame fun(self, value: boolean): nil + ---@field get_rider_offset fun(self, offset: Vec2): Vec2 + ---@field get_rider_offset_crouching fun(self, value: Vec2): Vec2 + ---@field get_jump_sound fun(self, double_jump: boolean): SOUNDID + ---@field get_attack_sound fun(self): SOUNDID + ---@field get_mounting_sound fun(self): SOUNDID + ---@field get_walking_sound fun(self): SOUNDID + ---@field get_untamed_loop_sound fun(self): SOUNDID ---@class Rockdog : Mount ---@field attack_cooldown integer @@ -3207,6 +3230,9 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field is_patrolling boolean ---@field aggro_trigger boolean @setting this makes him angry, if it's shopkeeper you get 2 aggro points ---@field was_hurt boolean @also is set true if you set aggro to true, get's trigger even when whipping + ---@field should_attack_on_sight fun(self): boolean + ---@field is_angry_flag_set fun(self): boolean + ---@field weapon_type fun(self): ENT_TYPE ---@class WalkingMonster : Monster ---@field chatting_to_uid integer @@ -3218,6 +3244,8 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field target_in_sight_timer integer ---@field ai_state integer ---@field aggro boolean @for bodyguard and shopkeeperclone it spawns a weapon as well + ---@field should_attack_on_sight fun(self): boolean + ---@field weapon_type fun(self): ENT_TYPE ---@class Ghost : Monster ---@field split_timer integer @for SMALL_HAPPY this is also the sequence timer of its various states @@ -3269,6 +3297,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field ceiling_pos_y number ---@field jump_timer integer @For the giant spider, some times he shot web instead of jumping ---@field trigger_distance number @only in the x coordinate + ---@field on_ceiling fun(self): boolean ---@class HangSpider : Monster ---@field dangle_jump_timer integer @@ -3283,7 +3312,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field shop_owner boolean ---@class Yang : RoomOwner - ---@field turkeys_in_den integer[] @Table of uid's of the turkeys, goes only up to 3, is nil when yang is angry + ---@field turkeys_in_den integer[] @Table of uids of the turkeys, goes only up to 3, is nil when yang is angry ---@field first_message_shown boolean @I'm looking for turkeys, wanna help? ---@field quest_incomplete boolean @Is set to false when the quest is over (Yang dead or second turkey delivered) ---@field special_message_shown boolean @Tusk palace/black market/one way door - message shown @@ -3787,8 +3816,13 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@class Projectile : Movable ---@class Purchasable : Movable + ---@field acquire fun(self, who: Entity): nil @Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money ---@class DummyPurchasableEntity : Purchasable + ---@field replace_entity Entity + ---@field exploding boolean + ---@field explosion_timer integer @Explodes when timer reaches 30 + ---@field trigger_explosion fun(self, who: Entity): nil @Transfers ownership etc. for who to blame, sets the exploding bool ---@class Bow : Purchasable ---@field get_arrow_special_offset fun(self): number @When lying on the ground @@ -3799,6 +3833,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@class Jetpack : Backpack ---@field flame_on boolean ---@field fuel integer + ---@field acceleration fun(self): number ---@class TeleporterBackpack : Backpack ---@field teleport_number integer @@ -3843,7 +3878,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field spawn_y number ---@class Spear : Movable - ---@field sound_id integer + ---@field sound_id SOUNDID ---@class JungleSpearCosmetic : Movable ---@field move_x number @@ -4010,6 +4045,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@class OlmecCannon : Movable ---@field timer integer ---@field bombs_left integer + ---@field spawn_projectile fun(self): nil ---@class Landmine : LightEmitter ---@field timer integer @explodes at 57, if you set it to 58 will count to overflow @@ -5048,13 +5084,19 @@ function CustomSound:play(paused, sound_type) end ---@class SoundMeta ---@field x number ---@field y number + ---@field sound_info SoundInfo ---@field left_channel number[] @size: 38 @Use VANILLA_SOUND_PARAM as index, warning: special case with first index at 0, loop using pairs will get you all results but the key/index will be wrong, ipairs will have correct key/index but will skip the first element ---@field right_channel number[] @size: 38 @Use VANILLA_SOUND_PARAM as index warning: special case with first index at 0, loop using pairs will get you all results but the key/index will be wrong, ipairs will have correct key/index but will skip the first element ---@field start_over boolean @when false, current track starts from the beginning, is immediately set back to true ---@field playing boolean @set to false to turn off + ---@field start fun(self): nil ---@class BackgroundSound : SoundMeta +---@class SoundInfo + ---@field sound_id SOUNDID + ---@field sound_name VANILLA_SOUND + ---@class PlayerSlotSettings ---@field controller_vibration boolean ---@field auto_run_enabled boolean @@ -11641,4 +11683,5 @@ local MAX_PLAYERS = 4 ---@alias uColor integer; ---@alias SHORT_TILE_CODE integer; ---@alias STRINGID integer; +---@alias SOUNDID integer; ---@alias FEAT integer; diff --git a/docs/src/includes/_enums.md b/docs/src/includes/_enums.md index 4065f64a7..67f124930 100644 --- a/docs/src/includes/_enums.md +++ b/docs/src/includes/_enums.md @@ -899,7 +899,7 @@ Name | Data | Description [POST_LEVEL_GENERATION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.POST_LEVEL_GENERATION) | ON::POST_LEVEL_GENERATION | Runs right after level generation is done, i.e. after all level gen entities are spawned, before any entities are updated. You can spawn your own entities here, like extra enemies, give items to players etc.
[POST_LOAD_SCREEN](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.POST_LOAD_SCREEN) | ON::POST_LOAD_SCREEN | Runs right after a screen is loaded, before rendering anything
[PRE_GET_RANDOM_ROOM](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.PRE_GET_RANDOM_ROOM) | ON::PRE_GET_RANDOM_ROOM | Params: int x, int y, [LAYER](#LAYER) layer, [ROOM_TEMPLATE](#ROOM_TEMPLATE) room_template
Return: `string room_data`
Called when the game wants to get a random room for a given template. Return a string that represents a room template to make the game use that.
If the size of the string returned does not match with the room templates expected size the room is discarded.
White spaces at the beginning and end of the string are stripped, not at the beginning and end of each line.
-[PRE_HANDLE_ROOM_TILES](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.PRE_HANDLE_ROOM_TILES) | ON::PRE_HANDLE_ROOM_TILES | Params: int x, int y, [ROOM_TEMPLATE](#ROOM_TEMPLATE) room_template, [PreHandleRoomTilesContext](#PreHandleRoomTilesContext) room_ctx
Return: `bool last_callback` to determine whether callbacks of the same type should be executed after this
Runs after a random room was selected and right before it would spawn entities for each tile code
Allows you to modify the rooms content in the front and back layer as well as add a backlayer if not yet existant
+[PRE_HANDLE_ROOM_TILES](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.PRE_HANDLE_ROOM_TILES) | ON::PRE_HANDLE_ROOM_TILES | Params: int x, int y, [ROOM_TEMPLATE](#ROOM_TEMPLATE) room_template, [PreHandleRoomTilesContext](#PreHandleRoomTilesContext) room_ctx
Return: `bool last_callback` to determine whether callbacks of the same type should be executed after this
Runs after a random room was selected and right before it would spawn entities for each tile code
Allows you to modify the rooms content in the front and back layer as well as add a back layer if not yet existant
[SCRIPT_ENABLE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.SCRIPT_ENABLE) | ON::SCRIPT_ENABLE | Runs when the script is enabled from the UI or when imported by another script while disabled, but not on load.
[SCRIPT_DISABLE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.SCRIPT_DISABLE) | ON::SCRIPT_DISABLE | Runs when the script is disabled from the UI and also right before unloading/reloading.
[RENDER_PRE_HUD](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.RENDER_PRE_HUD) | ON::RENDER_PRE_HUD | Params: [VanillaRenderContext](#VanillaRenderContext) render_ctx, [Hud](#Hud) hud
Runs before the HUD is drawn on screen. In this event, you can draw textures with the `draw_screen_texture` function of the render_ctx or edit the Hud values. Return `true` to skip rendering.
@@ -916,7 +916,7 @@ Name | Data | Description [RENDER_POST_LAYER](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.RENDER_POST_LAYER) | ON::RENDER_POST_LAYER | Params: [VanillaRenderContext](#VanillaRenderContext) render_ctx, int rendered_layer
Runs after a layer is rendered, runs for both layers during layer door transitions. Things drawn here will be part of the layer transition animation
[RENDER_PRE_LEVEL](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.RENDER_PRE_LEVEL) | ON::RENDER_PRE_LEVEL | Params: [VanillaRenderContext](#VanillaRenderContext) render_ctx, int camera_layer
Runs before the level is rendered. Return `true` to skip rendering.
[RENDER_POST_LEVEL](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.RENDER_POST_LEVEL) | ON::RENDER_POST_LEVEL | Params: [VanillaRenderContext](#VanillaRenderContext) render_ctx, int camera_layer
Runs after the level is rendered, before hud
-[RENDER_PRE_GAME](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.RENDER_PRE_GAME) | ON::RENDER_PRE_GAME | Params: [VanillaRenderContext](#VanillaRenderContext) render_ctx
Runs before the ingame part of the game is rendered. Return `true` to skip rendering.
+[RENDER_PRE_GAME](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.RENDER_PRE_GAME) | ON::RENDER_PRE_GAME | Params: [VanillaRenderContext](#VanillaRenderContext) render_ctx
Runs before the in-game part of the game is rendered. Return `true` to skip rendering.
[RENDER_POST_GAME](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.RENDER_POST_GAME) | ON::RENDER_POST_GAME | Params: [VanillaRenderContext](#VanillaRenderContext) render_ctx
Runs after the level and HUD are rendered, before pause menus and blur effects
[SPEECH_BUBBLE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.SPEECH_BUBBLE) | ON::SPEECH_BUBBLE | Params: [Entity](#Entity) speaking_entity, string text
Runs before any speech bubble is created, even the one using [say](#say) function
Return: if you don't return anything it will execute the speech bubble function normally with default message
if you return empty string, it will not create the speech bubble at all, if you return string, it will use that instead of the original
The first script to return string (empty or not) will take priority, the rest will receive callback call but the return behavior won't matter
[TOAST](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.TOAST) | ON::TOAST | Params: string text
Runs before any toast is created, even the one using [toast](#toast) function
Return: if you don't return anything it will execute the toast function normally with default message
if you return empty string, it will not create the toast at all, if you return string, it will use that instead of the original message
The first script to return string (empty or not) will take priority, the rest will receive callback call but the return behavior won't matter
diff --git a/docs/src/includes/_events.md b/docs/src/includes/_events.md index 77fbbb384..c8c36baca 100644 --- a/docs/src/includes/_events.md +++ b/docs/src/includes/_events.md @@ -332,7 +332,7 @@ Params: int x, int y, [LAYER](#LAYER) layer, [ROOM_TEMPLATE](#ROOM_TEMPLATE) roo > Search script examples for [ON.PRE_HANDLE_ROOM_TILES](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.PRE_HANDLE_ROOM_TILES) -Params: int x, int y, [ROOM_TEMPLATE](#ROOM_TEMPLATE) room_template, [PreHandleRoomTilesContext](#PreHandleRoomTilesContext) room_ctx
Return: `bool last_callback` to determine whether callbacks of the same type should be executed after this
Runs after a random room was selected and right before it would spawn entities for each tile code
Allows you to modify the rooms content in the front and back layer as well as add a backlayer if not yet existant
+Params: int x, int y, [ROOM_TEMPLATE](#ROOM_TEMPLATE) room_template, [PreHandleRoomTilesContext](#PreHandleRoomTilesContext) room_ctx
Return: `bool last_callback` to determine whether callbacks of the same type should be executed after this
Runs after a random room was selected and right before it would spawn entities for each tile code
Allows you to modify the rooms content in the front and back layer as well as add a back layer if not yet existant
## ON.SCRIPT_ENABLE @@ -471,7 +471,7 @@ Params: [VanillaRenderContext](#VanillaRenderContext) render_ctx, int camera_lay > Search script examples for [ON.RENDER_PRE_GAME](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ON.RENDER_PRE_GAME) -Params: [VanillaRenderContext](#VanillaRenderContext) render_ctx
Runs before the ingame part of the game is rendered. Return `true` to skip rendering.
+Params: [VanillaRenderContext](#VanillaRenderContext) render_ctx
Runs before the in-game part of the game is rendered. Return `true` to skip rendering.
## ON.RENDER_POST_GAME diff --git a/docs/src/includes/_globals.md b/docs/src/includes/_globals.md index 2b20f3721..b49181f75 100644 --- a/docs/src/includes/_globals.md +++ b/docs/src/includes/_globals.md @@ -771,7 +771,7 @@ Returns [PlayerGhost](#PlayerGhost) with this player slot 1..4 > Search script examples for [get_type](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_type) -#### [EntityDB](#EntityDB) get_type(int id) +#### [EntityDB](#EntityDB) get_type([ENT_TYPE](#ENT_TYPE) id) Get the [EntityDB](#EntityDB) behind an [ENT_TYPE](#ENT_TYPE)... @@ -1809,7 +1809,7 @@ Initializes some adventure run related values and loads the character select scr #### nil play_seeded(optional seed) -Initializes some seedeed run related values and loads the character select screen, as if starting a new seeded run after entering the seed. +Initializes some seeded run related values and loads the character select screen, as if starting a new seeded run after entering the seed. ### register_console_command @@ -2074,7 +2074,7 @@ Sets the specified setting temporarily. These values are not saved and might res #### nil set_speedhack(optional multiplier) -Set multiplier (default 1.0) for a QueryPerformanceCounter hook based speedhack, similar to the one in Cheat Engine. Call without arguments to reset. Also see set_frametime +Set multiplier (default 1.0) for a QueryPerformanceCounter hook based speedhack, similar to the one in Cheat Engine. Call without arguments to reset. Also see [set_frametime](#set_frametime) ### set_start_level_paused @@ -2812,7 +2812,7 @@ Get interpolated render position `x, y, layer` of entity by uid. This gives smoo #### tuple<float, float> get_velocity(int uid) -Get velocity `vx, vy` of an entity by uid. Use this, don't use `Entity.velocityx/velocityy` because those are relative to `Entity.overlay`. +Get velocity `vx, vy` of an entity by uid. Use this to get velocity relative to the game world, (the `Entity.velocityx/velocityy` are relative to `Entity.overlay`). Only works for movable or liquid entities ### get_window_size @@ -3045,7 +3045,7 @@ Change [ENT_TYPE](#ENT_TYPE)'s spawned in dice shops (Madame Tusk as well), by d ENT_TYPE_ITEM_PICKUP_SPIKESHOES, ENT_TYPE_ITEM_PICKUP_SPRINGSHOES, ITEM_MACHETE, ITEM_BOOMERANG, ITEM_CROSSBOW, ITEM_SHOTGUN, ITEM_FREEZERAY, ITEM_WEBGUN, ITEM_CAMERA, ITEM_MATTOCK, ITEM_PURCHASABLE_JETPACK, ITEM_PURCHASABLE_HOVERPACK, ITEM_TELEPORTER, ITEM_PURCHASABLE_TELEPORTER_BACKPACK, ITEM_PURCHASABLE_POWERPACK}
Min 6, Max 255, if you want less then 6 you need to write some of them more then once (they will have higher "spawn chance"). -If you use this function in the level with diceshop in it, you have to update `item_ids` in the [ITEM_DICE_PRIZE_DISPENSER](#PrizeDispenser). +If you use this function in the level with dice shop in it, you have to update `item_ids` in the [ITEM_DICE_PRIZE_DISPENSER](#PrizeDispenser). Use empty table as argument to reset to the game default ### is_inside_active_shop_room @@ -3098,6 +3098,18 @@ Spawn a [Shopkeeper](#Shopkeeper) in the coordinates and make the room their sho ## Sound functions +### convert_sound_id + + +> Search script examples for [convert_sound_id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=convert_sound_id) + +#### [VANILLA_SOUND](#VANILLA_SOUND) convert_sound_id([SOUNDID](#Aliases) id) + +#### [SOUNDID](#Aliases) convert_sound_id([VANILLA_SOUND](#VANILLA_SOUND) sound) + +Convert [SOUNDID](#Aliases) to [VANILLA_SOUND](#VANILLA_SOUND) and vice versa + + ### create_sound @@ -3123,6 +3135,10 @@ Gets an existing sound, either if a file at the same path was already loaded or #### [SoundMeta](#SoundMeta) play_sound([VANILLA_SOUND](#VANILLA_SOUND) sound, int source_uid) +#### [SoundMeta](#SoundMeta) play_sound([SOUNDID](#Aliases) sound_id, int source_uid) + +Use source_uid to make the sound be played at the location of that entity, set it -1 to just play it "everywhere" +Returns [SoundMeta](#SoundMeta), beware that the sound can't be stopped (`start_over` and `playing` are unavailable). Should only be used for sfx. ## Spawn functions @@ -3476,7 +3492,7 @@ Returns [STRINGID](#Aliases) of the new string #### nil change_string([STRINGID](#Aliases) id, string str) -Change string at the given id (don't use stringid diretcly for vanilla string, use `hash_to_stringid` first) +Change string at the given id (**don't use stringid directly for vanilla string**, use [hash_to_stringid](#hash_to_stringid) first) This edits custom string and in game strings but changing the language in settings will reset game strings ### clear_custom_name @@ -3540,7 +3556,7 @@ Same as `Player.get_short_name` #### string get_string([STRINGID](#Aliases) string_id) -Get string behind [STRINGID](#Aliases), don't use stringid directly for vanilla string, use [hash_to_stringid](#hash_to_stringid) first +Get string behind [STRINGID](#Aliases), **don't use stringid directly for vanilla string**, use [hash_to_stringid](#hash_to_stringid) first Will return the string of currently choosen language ### hash_to_stringid diff --git a/docs/src/includes/_home.md b/docs/src/includes/_home.md index 13560a5e4..6af86ad2f 100644 --- a/docs/src/includes/_home.md +++ b/docs/src/includes/_home.md @@ -162,4 +162,5 @@ Flags | int; uColor | int; SHORT_TILE_CODE | int; STRINGID | int; +SOUNDID | int; FEAT | int; diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 00f0a1de2..989461625 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -457,10 +457,10 @@ int | [search_flags](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=se float | [width](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=width) | float | [height](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=height) | int | [draw_depth](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=draw_depth) | -float | [offsetx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=offsetx) | -float | [offsety](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=offsety) | -float | [hitboxx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=hitboxx) | -float | [hitboxy](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=hitboxy) | +float | [offsetx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=offsetx) | Offset of the hitbox in relation to the entity position +float | [offsety](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=offsety) | Offset of the hitbox in relation to the entity position +float | [hitboxx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=hitboxx) | Half of the width of the hitbox +float | [hitboxy](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=hitboxy) | Half of the height of the hitbox [SHAPE](#SHAPE) | [default_shape](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_shape) | bool | [default_hitbox_enabled](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_hitbox_enabled) | int | [collision2_mask](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=collision2_mask) | [MASK](#MASK), will only call collision2 when colliding with entities that match this mask. @@ -2826,6 +2826,14 @@ map<[VANILLA_SOUND_PARAM](#VANILLA_SOUND_PARAM), string> | [get_parameters optional<float> | [get_parameter(VANILLA_SOUND_PARAM parameter_index)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_parameter) | bool | [set_parameter(VANILLA_SOUND_PARAM parameter_index, float value)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_parameter) | +### SoundInfo + + +Type | Name | Description +---- | ---- | ----------- +[SOUNDID](#Aliases) | [sound_id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound_id) | +[VANILLA_SOUND](#VANILLA_SOUND) | [sound_name](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound_name) | + ### SoundMeta @@ -2833,10 +2841,12 @@ Type | Name | Description ---- | ---- | ----------- float | [x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=x) | float | [y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=y) | +[SoundInfo](#SoundInfo) | [sound_info](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound_info) | array<float, 38> | [left_channel](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=left_channel) | Use [VANILLA_SOUND_PARAM](#VANILLA_SOUND_PARAM) as index, warning: special case with first index at 0, loop using pairs will get you all results but the key/index will be wrong, ipairs will have correct key/index but will skip the first element array<float, 38> | [right_channel](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=right_channel) | Use [VANILLA_SOUND_PARAM](#VANILLA_SOUND_PARAM) as index warning: special case with first index at 0, loop using pairs will get you all results but the key/index will be wrong, ipairs will have correct key/index but will skip the first element bool | [start_over](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=start_over) | when false, current track starts from the beginning, is immediately set back to true bool | [playing](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=playing) | set to false to turn off +nil | [start()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=start) | ## State types @@ -4089,7 +4099,7 @@ Derived from [Entity](#Entity) [Floor](#Floor) Type | Name | Description ---- | ---- | ----------- [ENT_TYPE](#ENT_TYPE) | [spawn_entity_type](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_entity_type) | -int | [first_sound_id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=first_sound_id) | +[SOUNDID](#Aliases) | [first_sound_id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=first_sound_id) | nil | [trigger(int who_uid, bool left)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=trigger) | The uid must be movable entity for ownership transfers ### TransferFloor @@ -4229,8 +4239,7 @@ float | [offsetx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=offse float | [offsety](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=offsety) | Offset of the hitbox in relation to the entity position [RenderInfo](#RenderInfo) | [rendering_info](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=rendering_info) | any | [user_data](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=user_data) | You can put any arbitrary lua object here for custom entities or player stats, which is then saved across level transitions for players and carried items, mounts etc... This field is local to the script and multiple scripts can write different things in the same entity. The data is saved right before [ON](#ON).PRE_LOAD_SCREEN from a level and loaded right before [ON](#ON).POST_LOAD_SCREEN to a level or transition. It is not available yet in post_entity_spawn, but that is a good place to initialize it for new custom entities. See example for more.
-[Entity](#Entity) | [topmost()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=topmost) | -[Entity](#Entity) | [topmost_mount()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=topmost_mount) | +[Entity](#Entity) | [topmost()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=topmost) | Returns the top entity in a chain (overlay) bool | [overlaps_with(AABB hitbox)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=overlaps_with) | bool | [overlaps_with(float rect_left, float rect_bottom, float rect_right, float rect_top)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=overlaps_with) | Deprecated
Use `overlaps_with(AABB hitbox)` instead bool | [overlaps_with(Entity other)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=overlaps_with) | @@ -4240,7 +4249,7 @@ nil | [set_draw_depth(int draw_depth, int b3f)](https://github.com/spelunky-fyi/ nil | [reset_draw_depth()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=reset_draw_depth) | nil | [liberate_from_shop(bool clear_parrent)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=liberate_from_shop) | `clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 [Entity](#Entity) | [get_held_entity()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_held_entity) | -nil | [set_layer(LAYER layer)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_layer) | Moves the entity to specified layer, nothing else happens, so this does not emulate a door transition +nil | [set_layer(LAYER layer)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_layer) | Moves the entity to specified layer with all it's items, nothing else happens, so this does not emulate a door transition nil | [apply_layer()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apply_layer) | Adds the entity to its own layer, to add it to entity lookup tables without waiting for a state update nil | [remove()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=remove) | Moves the entity to the limbo-layer where it can later be retrieved from again via `respawn` nil | [respawn(LAYER layer_to)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=respawn) | Moves the entity from the limbo-layer (where it was previously put by `remove`) to `layer` @@ -4265,6 +4274,8 @@ nil | [update()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=update nil | [flip(bool left)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=flip) | nil | [remove_item(Entity entity, bool autokill_check)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=remove_item) | nil | [apply_db()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apply_db) | Applies changes made in `entity.type` +[Vec2](#Vec2) | [get_absolute_velocity()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_absolute_velocity) | Get's the velocity relative to the game world, only for movable or liquid entities +[AABB](#AABB) | [get_hitbox(optional use_render_pos)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_hitbox) | `use_render_pos` default is `false` [CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. [CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. @@ -5357,6 +5368,13 @@ bool | [used_double_jump()](https://github.com/spelunky-fyi/overlunky/search?l=L nil | [remove_rider()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=remove_rider) | nil | [carry(Movable rider)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=carry) | nil | [tame(bool value)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=tame) | +[Vec2](#Vec2) | [get_rider_offset(Vec2 offset)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_rider_offset) | +[Vec2](#Vec2) | [get_rider_offset_crouching(Vec2 value)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_rider_offset_crouching) | +[SOUNDID](#Aliases) | [get_jump_sound(bool double_jump)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_jump_sound) | +[SOUNDID](#Aliases) | [get_attack_sound()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_attack_sound) | +[SOUNDID](#Aliases) | [get_mounting_sound()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_mounting_sound) | +[SOUNDID](#Aliases) | [get_walking_sound()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_walking_sound) | +[SOUNDID](#Aliases) | [get_untamed_loop_sound()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_untamed_loop_sound) | ### Mummy @@ -5378,6 +5396,8 @@ float | [climb_direction](https://github.com/spelunky-fyi/overlunky/search?l=Lua int | [target_in_sight_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=target_in_sight_timer) | int | [ai_state](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ai_state) | bool | [aggro](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=aggro) | for bodyguard and shopkeeperclone it spawns a weapon as well +bool | [should_attack_on_sight()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=should_attack_on_sight) | +[ENT_TYPE](#ENT_TYPE) | [weapon_type()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=weapon_type) | ### Necromancer @@ -5475,7 +5495,7 @@ string | [get_name()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=g string | [get_short_name()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_short_name) | Get the short name of the character, this will be the modded name not only the vanilla name. [Color](#Color) | [get_heart_color()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_heart_color) | Get the heart color of the character, this will be the modded heart color not only the vanilla heart color. bool | [is_female()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_female) | Check whether the character is female, will be `true` if the character was modded to be female as well. -nil | [set_heart_color(Color hcolor)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_heart_color) | Set the heart color the character. +nil | [set_heart_color(Color hcolor)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_heart_color) | Set the heart color for the character. nil | [let_go()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=let_go) | Drops from ladders, ropes and ledge grabs ### PowerupCapable @@ -5559,6 +5579,9 @@ int | [countdown_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q bool | [is_patrolling](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_patrolling) | bool | [aggro_trigger](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=aggro_trigger) | setting this makes him angry, if it's shopkeeper you get 2 aggro points bool | [was_hurt](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=was_hurt) | also is set true if you set aggro to true, get's trigger even when whipping +bool | [should_attack_on_sight()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=should_attack_on_sight) | +bool | [is_angry_flag_set()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_angry_flag_set) | +[ENT_TYPE](#ENT_TYPE) | [weapon_type()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=weapon_type) | ### Scarab @@ -5628,6 +5651,7 @@ float | [ceiling_pos_x](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q float | [ceiling_pos_y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ceiling_pos_y) | int | [jump_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=jump_timer) | For the giant spider, some times he shot web instead of jumping float | [trigger_distance](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=trigger_distance) | only in the x coordinate +bool | [on_ceiling()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=on_ceiling) | ### Tadpole @@ -5791,7 +5815,7 @@ Derived from [Entity](#Entity) [Movable](#Movable) [PowerupCapable](#PowerupCapa Type | Name | Description ---- | ---- | ----------- -set<int> | [turkeys_in_den](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=turkeys_in_den) | Table of uid's of the turkeys, goes only up to 3, is nil when yang is angry +set<int> | [turkeys_in_den](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=turkeys_in_den) | Table of uids of the turkeys, goes only up to 3, is nil when yang is angry bool | [first_message_shown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=first_message_shown) | I'm looking for turkeys, wanna help? bool | [quest_incomplete](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=quest_incomplete) | Is set to false when the quest is over ([Yang](#Yang) dead or second turkey delivered) bool | [special_message_shown](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=special_message_shown) | Tusk palace/black market/one way door - message shown @@ -6175,6 +6199,10 @@ Derived from [Entity](#Entity) [Movable](#Movable) [Purchasable](#Purchasable) Type | Name | Description ---- | ---- | ----------- +[Entity](#Entity) | [replace_entity](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=replace_entity) | +bool | [exploding](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=exploding) | +int | [explosion_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=explosion_timer) | Explodes when timer reaches 30 +nil | [trigger_explosion(Entity who)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=trigger_explosion) | Transfers ownership etc. for who to blame, sets the exploding bool ### EggSac @@ -6722,6 +6750,7 @@ Type | Name | Description ---- | ---- | ----------- bool | [flame_on](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=flame_on) | int | [fuel](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=fuel) | +float | [acceleration()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=acceleration) | ### JungleSpearCosmetic @@ -7081,6 +7110,7 @@ Type | Name | Description ---- | ---- | ----------- int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | int | [bombs_left](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=bombs_left) | +nil | [spawn_projectile()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_projectile) | ### OlmecFloater @@ -7217,6 +7247,7 @@ Derived from [Entity](#Entity) [Movable](#Movable) Type | Name | Description ---- | ---- | ----------- +nil | [acquire(Entity who)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=acquire) | Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money ### PushBlock @@ -7354,7 +7385,7 @@ Derived from [Entity](#Entity) [Movable](#Movable) Type | Name | Description ---- | ---- | ----------- -int | [sound_id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound_id) | +[SOUNDID](#Aliases) | [sound_id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound_id) | ### SpecialShot diff --git a/src/game_api/aliases.hpp b/src/game_api/aliases.hpp index 0d84cd23d..c50eee380 100644 --- a/src/game_api/aliases.hpp +++ b/src/game_api/aliases.hpp @@ -66,6 +66,7 @@ using IMAGE = int64_t; // NoAlias using WORLD_SHADER = uint8_t; // NoAlias using SHORT_TILE_CODE = uint8_t; using STRINGID = uint32_t; +using SOUNDID = int32_t; using FEAT = uint8_t; using KEY = int64_t; // NoAlias using RAW_KEY = int8_t; // NoAlias diff --git a/src/game_api/entities_activefloors.cpp b/src/game_api/entities_activefloors.cpp index 47f0d5393..ba2abf8ee 100644 --- a/src/game_api/entities_activefloors.cpp +++ b/src/game_api/entities_activefloors.cpp @@ -43,5 +43,5 @@ void Drill::trigger(std::optional play_sound_effect) sound2 = construct_soundmeta(0x153, false); sound2->start(); if (play_sound_effect.value_or(false)) - play_sound_by_id(0xA4, uid); + play_sound(0xA4, uid); } diff --git a/src/game_api/entities_chars.hpp b/src/game_api/entities_chars.hpp index d58fdb885..c9ae9b5b2 100644 --- a/src/game_api/entities_chars.hpp +++ b/src/game_api/entities_chars.hpp @@ -146,7 +146,7 @@ class Player : public PowerupCapable /// Check whether the character is female, will be `true` if the character was modded to be female as well. bool is_female(); - /// Set the heart color the character. + /// Set the heart color for the character. void set_heart_color(Color hcolor); /// Drops from ladders, ropes and ledge grabs void let_go(); diff --git a/src/game_api/entities_floors.cpp b/src/game_api/entities_floors.cpp index 4523c5129..ee7c0d8c9 100644 --- a/src/game_api/entities_floors.cpp +++ b/src/game_api/entities_floors.cpp @@ -37,7 +37,7 @@ void Floor::fix_border_tile_animation() } else { - auto [x_pos, y_pos] = position(); + auto [x_pos, y_pos] = abs_position(); auto base_x = static_cast(std::floor(x_pos / 2.0f)); auto base_y = static_cast(std::floor(y_pos / 2.0f)); auto sub_index_x = static_cast(std::floor(x_pos - base_x * 2)); diff --git a/src/game_api/entities_floors.hpp b/src/game_api/entities_floors.hpp index d2fc85270..9f3db7b93 100644 --- a/src/game_api/entities_floors.hpp +++ b/src/game_api/entities_floors.hpp @@ -189,7 +189,7 @@ class TotemTrap : public Floor float unknown2; // might be sound delay related, cannot reproduce anymore float unknown3; ENT_TYPE spawn_entity_type; - uint32_t first_sound_id; + SOUNDID first_sound_id; int32_t counter; // adds some value depending on trap and with side is triggered, setting to low value pauses it? uint8_t unknown4; // forced to 1 uint8_t unused1; diff --git a/src/game_api/entities_items.hpp b/src/game_api/entities_items.hpp index 1604008f7..fd68c8f2b 100644 --- a/src/game_api/entities_items.hpp +++ b/src/game_api/entities_items.hpp @@ -21,13 +21,14 @@ struct SpritePosition; class Powerup : public Movable { public: - virtual SpritePosition& get_hud_sprite(SpritePosition&) = 0; + virtual SpritePosition& get_hud_sprite(SpritePosition& output) = 0; // not sure why the normal powerups use apply/remove effect where backpacks use the put on/put off virtual void apply_effect(PowerupCapable* who) = 0; - virtual void remove_effect(PowerupCapable* who) = 0; + virtual void remove_effect(PowerupCapable* who) = 0; // does not remove powerup from the powerups map virtual void on_putting_on(PowerupCapable* who) = 0; // only for backpacks, sets offsets etc. virtual void on_putting_off(PowerupCapable* who) = 0; - virtual bool in_use() = 0; // for jetpack returns jetpack.flame_on, for capes Cape.floating_down, for hoverpack hoverpack.is_on, teleporter and powerpack and all other powerups return false + /// for jetpack returns jetpack.flame_on, for capes Cape.floating_down, for hoverpack hoverpack.is_on, teleporter and powerpack and all other powerups return false + virtual bool in_use() = 0; }; class Backpack : public Powerup @@ -51,7 +52,7 @@ class Jetpack : public Backpack uint32_t fly_time; // it's per level, not even per jetpack lol, it also adds at when it explodes uint16_t fuel; // only set the fuel for an equipped jetpack (player->items)! - virtual float jetpack_acceleration() = 0; + virtual float acceleration() = 0; }; class TeleporterBackpack : public Backpack @@ -97,7 +98,9 @@ class VladsCape : public Cape class Purchasable : public Movable { public: - virtual void buy(Entity* who) = 0; + /// Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop. + /// does not consume money + virtual void acquire(Entity* who) = 0; }; class DummyPurchasableEntity : public Purchasable @@ -105,6 +108,8 @@ class DummyPurchasableEntity : public Purchasable public: Entity* replace_entity; bool exploding; + /// Explodes when timer reaches 30 + uint8_t explosion_timer; /// Transfers ownership etc. for who to blame, sets the exploding bool virtual void trigger_explosion(Entity* who) = 0; @@ -201,7 +206,7 @@ class Idol : public Movable class Spear : public Movable { public: - uint32_t sound_id; + SOUNDID sound_id; }; class JungleSpearCosmetic : public Movable @@ -220,9 +225,11 @@ struct UnknownPointerGroup class Projectile : public Movable { - // called when shooting (entity it still not added to layer) and it's called like normal function, not thru this virtual + // depending on the entity can be called directly instead of vtable (example: plasma cannnon) + + // called when shooting (entity it still not added to layer), sets the initial velocities and owner virtual void v93(float angle, float speed, Entity* responsible) = 0; - // called when shooting (entity it still not added to layer) + // called when shooting (entity it still not added to layer), returns false when the responsible doesn't have overlay, checks if the verlay is MASK.ITEM and bunch of other stuff virtual bool v94(Entity* responsible, float x) = 0; }; diff --git a/src/game_api/entities_monsters.hpp b/src/game_api/entities_monsters.hpp index 33064b43a..7ffa04fd8 100644 --- a/src/game_api/entities_monsters.hpp +++ b/src/game_api/entities_monsters.hpp @@ -237,7 +237,7 @@ class Shopkeeper : public RoomOwner class Yang : public RoomOwner { public: - /// Table of uid's of the turkeys, goes only up to 3, is nil when yang is angry + /// Table of uids of the turkeys, goes only up to 3, is nil when yang is angry custom_set turkeys_in_den; uint8_t unknown4; uint8_t unknown5; diff --git a/src/game_api/entities_mounts.hpp b/src/game_api/entities_mounts.hpp index 8afaa1720..77e0cb739 100644 --- a/src/game_api/entities_mounts.hpp +++ b/src/game_api/entities_mounts.hpp @@ -12,18 +12,16 @@ struct SoundMeta; class Mount : public PowerupCapable { public: - // size_t unknown1; - // uint64_t unknown2; int32_t rider_uid; // who rides it - uint32_t unknown4; + uint32_t padding1; SoundMeta* sound; bool can_doublejump; // whether the doublejump has already occurred or not bool tamed; uint16_t walk_pause_timer; // alternates between walking and pausing every time it reaches zero uint8_t unknown9a; - uint8_t unknown9b; + bool double_jumping; // used to play different animation for the double jump then the standard jump, is true for less then a frame uint8_t taming_timer; // when 0 it's tame - uint8_t unknown9d; + uint8_t padding2; void carry(Movable* rider); @@ -33,18 +31,18 @@ class Mount : public PowerupCapable flags = flags | 0x20000; } - virtual Vec2& get_special_offset(Vec2& offset) = 0; // 95, gets special offset for the raider when jumping on mount - virtual Vec2& v96(Vec2& value) = 0; // 96, gets something for when crouching on mount - virtual bool used_double_jump() = 0; // 97, checks can_doublejump and unknown9b - virtual uint32_t get_jump_sound(bool double_jump) = 0; // 98 - virtual uint32_t get_attack_sound() = 0; // 99 - virtual void play_jump_on_sound() = 0; // 100, checks if it has rider etc. get's sound from 103 virtual - virtual void remove_rider() = 0; // 101 - virtual float v102() = 0; // 102, get offset? mech returns 0.9, the rest 0.5 - virtual uint32_t get_mount_sound() = 0; // 103, all return the VANILLA_SOUND.MOUNTS_MOUNT sound id - virtual uint32_t get_walking_sound() = 0; // 104 - virtual uint32_t get_untamed_loop_sound() = 0; // 105 - virtual bool can_play_mount_sound() = 0; // 106, called every frame, if returns true mount will make a sound + virtual Vec2& get_rider_offset(Vec2& offset) = 0; // 95 + virtual Vec2& get_rider_offset_crouching(Vec2& value) = 0; // 96 + virtual bool used_double_jump() = 0; // 97, (can_doublejump | double_jumping) + virtual SOUNDID get_jump_sound(bool double_jump) = 0; // 98 + virtual SOUNDID get_attack_sound() = 0; // 99 + virtual void play_jump_on_sound() = 0; // 100, checks if it has rider etc. get's sound from 103 virtual + virtual void remove_rider() = 0; // 101 + virtual float v102() = 0; // 102, mech returns 0.9, the rest 0.5, related to distance at which the player can mount + virtual SOUNDID get_mounting_sound() = 0; // 103 + virtual SOUNDID get_walking_sound() = 0; // 104 + virtual SOUNDID get_untamed_loop_sound() = 0; // 105 + virtual bool can_play_mount_sound() = 0; // 106, called every frame, if returns true mount will make a sound }; class Rockdog : public Mount diff --git a/src/game_api/entity.cpp b/src/game_api/entity.cpp index 379fdb16b..0c3d895da 100644 --- a/src/game_api/entity.cpp +++ b/src/game_api/entity.cpp @@ -30,66 +30,6 @@ using namespace std::chrono_literals; -void Entity::teleport(float dx, float dy, bool s, float vx, float vy, bool snap) -{ - if (overlay) - overlay->remove_item(this, false); - - auto topmost = topmost_mount(); // we just detached from overlay, why do we check this? - if (!s) - { - auto [x_pos, y_pos] = topmost->position(); - // player relative coordinates - x_pos += dx; - y_pos += dy; - if (snap) - { - x_pos = round(x_pos); - y_pos = round(y_pos); - } - topmost->x = x_pos; - topmost->y = y_pos; - } - else - { - // screen coordinates -1..1 - // log::debug!("Teleporting to screen {}, {}", x, y); - auto& state = State::get(); - auto [x_pos, y_pos] = state.click_position(dx, dy); - if (snap && abs(vx) + abs(vy) <= 0.04f) - { - x_pos = round(x_pos); - y_pos = round(y_pos); - } - // log::debug!("Teleporting to {}, {}", x, y); - topmost->x = x_pos; - topmost->y = y_pos; - } - // set velocity - if (topmost->is_movable()) - { - auto movable_ent = (Movable*)topmost; - movable_ent->velocityx = vx; - movable_ent->velocityy = vy; - } - return; -} - -void Entity::teleport_abs(float dx, float dy, float vx, float vy) -{ - if (overlay) - overlay->remove_item(this, false); - - x = dx; - y = dy; - if (is_movable()) - { - auto movable_ent = this->as(); - movable_ent->velocityx = vx; - movable_ent->velocityy = vy; - } -} - void Entity::set_layer(LAYER layer_to) { uint8_t dest_layer = enum_to_layer(layer_to); @@ -163,8 +103,11 @@ void Entity::perform_teleport(uint8_t delta_x, uint8_t delta_y) tp(this, delta_x, delta_y); } -Vec2 Entity::position() const +Vec2 Entity::abs_position() const { + if (abs_x != -FLT_MAX && abs_y != -FLT_MAX) // shortcut, if available + return {abs_x, abs_y}; + auto [x_pos, y_pos] = position_self(); // overlay exists if player is riding something / etc @@ -178,13 +121,6 @@ Vec2 Entity::position() const return {x_pos, y_pos}; } -void Entity::remove_item_uid(uint32_t item_uid, bool check_autokill) -{ - auto entity = get_entity_ptr(item_uid); - if (entity) - remove_item(entity, check_autokill); -} - void Movable::poison(int16_t frames) { static const size_t offset_first = get_address("first_poison_tick_timer_default"); @@ -199,70 +135,45 @@ void Movable::poison(int16_t frames) write_mem_prot(offset_subsequent, frames, true); } -std::tuple get_position(uint32_t uid) +Vec2 Entity::get_absolute_velocity() const { - Entity* ent = get_entity_ptr(uid); - if (ent) - return std::make_tuple(ent->position().x, ent->position().y, ent->layer); - - return {0.0f, 0.0f, (uint8_t)0}; -} - -std::tuple get_render_position(uint32_t uid) -{ - Entity* ent = get_entity_ptr(uid); - if (ent) + Vec2 velocity; + if (is_movable()) { - if (ent->rendering_info != nullptr && !ent->rendering_info->render_inactive) - return std::make_tuple(ent->rendering_info->x, ent->rendering_info->y, ent->layer); - else - return get_position(uid); + auto mov = static_cast(this); + velocity.x = mov->velocityx; + velocity.y = mov->velocityy; } - return {0.0f, 0.0f, (uint8_t)0}; -} - -std::tuple get_velocity(uint32_t uid) -{ - if (Entity* ent = get_entity_ptr(uid)) + else if (is_liquid()) { - float vx{0.0f}; - float vy{0.0f}; - if (ent->is_movable()) - { - Movable* mov = ent->as(); - vx = mov->velocityx; - vy = mov->velocityy; - } - else if (ent->is_liquid()) - { - auto liquid_engine = State::get().get_correct_liquid_engine(ent->type->id); - vx = liquid_engine->entity_velocities->x; - vy = liquid_engine->entity_velocities->y; - } - if (ent->overlay) - { - auto [ovx, ovy] = get_velocity(ent->overlay->uid); - vx += ovx; - vy += ovy; - } - return std::tuple{vx, vy}; + auto liquid_engine = State::get().get_correct_liquid_engine(type->id); + velocity.x = liquid_engine->entity_velocities->x; + velocity.y = liquid_engine->entity_velocities->y; } - return std::tuple{0.0f, 0.0f}; + + if (overlay) + velocity += overlay->get_absolute_velocity(); + + return velocity; } -AABB get_hitbox(uint32_t uid, bool use_render_pos) +AABB Entity::get_hitbox(std::optional use_render_pos) const { - if (Entity* ent = get_entity_ptr(uid)) + Vec2 pos; + if (use_render_pos.value_or(false) && rendering_info && !rendering_info->render_inactive) { - auto [x, y, l] = (use_render_pos ? get_render_position : get_position)(uid); - return AABB{ - x - ent->hitboxx + ent->offsetx, - y + ent->hitboxy + ent->offsety, - x + ent->hitboxx + ent->offsetx, - y - ent->hitboxy + ent->offsety, - }; + pos.x = rendering_info->x; + pos.y = rendering_info->y; } - return AABB{0.0f, 0.0f, 0.0f, 0.0f}; + else + pos = abs_position(); + + return AABB{ + pos.x - hitboxx + offsetx, + pos.y + hitboxy + offsety, + pos.x + hitboxx + offsetx, + pos.y - hitboxy + offsety, + }; } TEXTURE Entity::get_texture() const @@ -323,14 +234,6 @@ void Entity::set_enable_turning(bool enabled) set_entity_turning(this, enabled); } -std::vector Entity::get_items() -{ - if (items.size) - return std::vector(items.uids().begin(), items.uids().end()); - - return {}; -} - Entity* get_entity_ptr(uint32_t uid) { auto p = State::find(State::get().ptr(), uid); diff --git a/src/game_api/entity.hpp b/src/game_api/entity.hpp index 268e3624f..0a7c1cad8 100644 --- a/src/game_api/entity.hpp +++ b/src/game_api/entity.hpp @@ -110,18 +110,18 @@ class Entity /* for the autodoc any user_data; */ - - size_t pointer() + // {x, y} + Vec2 position_self() const { - return (size_t)this; + return Vec2{x, y}; } - - Vec2 position() const; - - void teleport(float dx, float dy, bool s, float vx, float vy, bool snap); - void teleport_abs(float dx, float dy, float vx, float vy); - - /// Moves the entity to specified layer, nothing else happens, so this does not emulate a door transition + // get the absolute position + Vec2 abs_position() const; + /// Get's the velocity relative to the game world, only for movable or liquid entities + Vec2 get_absolute_velocity() const; + /// `use_render_pos` default is `false` + AABB get_hitbox(std::optional use_render_pos) const; + /// Moves the entity to specified layer with all it's items, nothing else happens, so this does not emulate a door transition void set_layer(LAYER layer); /// Adds the entity to its own layer, to add it to entity lookup tables without waiting for a state update void apply_layer(); @@ -134,7 +134,7 @@ class Entity } /// Performs a teleport as if the entity had a teleporter and used it. The delta coordinates are where you want the entity to teleport to relative to its current position, in tiles (so integers, not floats). Positive numbers = to the right and up, negative left and down. void perform_teleport(uint8_t delta_x, uint8_t delta_y); - + /// Returns the top entity in a chain (overlay) Entity* topmost() { auto cur = this; @@ -144,7 +144,7 @@ class Entity } return cur; } - + /// NoDoc Entity* topmost_mount() { auto topmost = this; @@ -169,7 +169,7 @@ class Entity /// Use `overlaps_with(AABB hitbox)` instead bool overlaps_with(float rect_left, float rect_bottom, float rect_right, float rect_top) const { - const auto [posx, posy] = position(); + const auto [posx, posy] = abs_position(); const float left = posx - hitboxx + offsetx; const float right = posx + hitboxx + offsetx; const float bottom = posy - hitboxy + offsety; @@ -180,7 +180,7 @@ class Entity bool overlaps_with(Entity* other) const { - const auto [other_posx, other_posy] = other->position(); + const auto [other_posx, other_posy] = other->abs_position(); const float other_left = other_posx - other->hitboxx + other->offsetx; const float other_right = other_posx + other->hitboxx + other->offsetx; const float other_top = other_posy + other->hitboxy + other->offsety; @@ -189,12 +189,6 @@ class Entity return overlaps_with(other_left, other_bottom, other_right, other_top); } - Vec2 position_self() const - { - return Vec2{x, y}; - } - void remove_item_uid(uint32_t item_uid, bool check_autokill); - TEXTURE get_texture() const; /// Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one bool set_texture(TEXTURE texture_id); @@ -207,25 +201,10 @@ class Entity return more_flags & 0x4000; }; - // for supporting HookableVTable - uint32_t get_aux_id() const - { - return uid; - } - - // Needed despite HookableVTable for cleanup of arbitrary entity related data - std::uint32_t set_on_dtor(std::function cb) - { - return hook_dtor_impl(this, std::move(cb)); - } - void clean_on_dtor(std::uint32_t dtor_cb_id) + std::vector get_items() const { - clear_dtor_impl(this, dtor_cb_id); + return std::vector(items.uids().begin(), items.uids().end()); } - /// NoDoc - void set_enable_turning(bool enabled); - - std::vector get_items(); /// Kill entity along with all entities attached to it. Be aware that for example killing push block with this function will also kill anything on top of it, any items, players, monsters etc. /// To avoid that, you can inclusively or exclusively limit certain MASK and ENT_TYPE. Note: the function will first check mask, if the entity doesn't match, it will look in the provided ENT_TYPE's @@ -245,12 +224,27 @@ class Entity destroy_recursive(std::nullopt, {}, RECURSIVE_MODE::NONE); } + // for supporting HookableVTable + uint32_t get_aux_id() const + { + return uid; + } + // Needed despite HookableVTable for cleanup of arbitrary entity related data + std::uint32_t set_on_dtor(std::function cb) + { + return hook_dtor_impl(this, std::move(cb)); + } + void clean_on_dtor(std::uint32_t dtor_cb_id) + { + clear_dtor_impl(this, dtor_cb_id); + } + /// NoDoc + void set_enable_turning(bool enabled); template T* as() { return static_cast(this); } - static void set_hook_dtor_impl( std::function)> hook_fun, std::function clear_fun) @@ -318,12 +312,4 @@ class Entity virtual void apply_db() = 0; // 36, This is actually just an initialize call that is happening once after the entity is created }; -std::tuple get_position(uint32_t uid); -std::tuple get_render_position(uint32_t uid); - -std::tuple get_velocity(uint32_t uid); - -AABB get_hitbox(uint32_t uid, bool use_render_pos); - -struct EntityFactory* entity_factory(); Entity* get_entity_ptr(uint32_t uid); diff --git a/src/game_api/entity_db.cpp b/src/game_api/entity_db.cpp index df8c803b6..717ee2bec 100644 --- a/src/game_api/entity_db.cpp +++ b/src/game_api/entity_db.cpp @@ -48,7 +48,7 @@ std::vector list_entities() if (!entity_factory_ptr) return {}; - const EntityMap& map = entity_factory_ptr->entity_map; + const auto& map = entity_factory_ptr->entity_map; std::vector result; for (const auto& [name, id] : map) @@ -58,7 +58,7 @@ std::vector list_entities() return result; } -EntityDB* get_type(uint32_t id) +EntityDB* get_type(ENT_TYPE id) { EntityFactory* entity_factory_ptr = entity_factory(); @@ -73,12 +73,16 @@ EntityDB* get_type(uint32_t id) ENT_TYPE to_id(std::string_view name) { - const EntityFactory* entity_factory_ptr = entity_factory(); - if (!entity_factory_ptr) - return {}; - const EntityMap& map = entity_factory_ptr->entity_map; - auto it = map.find(std::string(name)); - return it != map.end() ? it->second : -1; + static const std::unordered_map* map; + if (map == nullptr) + { + const EntityFactory* entity_factory_ptr = entity_factory(); + if (!entity_factory_ptr) + return -1; + map = &entity_factory_ptr->entity_map; + } + auto it = map->find(std::string(name)); + return it != map->end() ? it->second : -1; } std::string_view to_name(ENT_TYPE id) @@ -89,11 +93,8 @@ std::string_view to_name(ENT_TYPE id) for (const auto& [name, type_id] : entity_factory_ptr->entity_map) { if (type_id == id) - { return name; - } } } - return {}; } diff --git a/src/game_api/entity_db.hpp b/src/game_api/entity_db.hpp index 0b2f2b848..a17bf20ed 100644 --- a/src/game_api/entity_db.hpp +++ b/src/game_api/entity_db.hpp @@ -46,9 +46,13 @@ struct EntityDB { struct { + /// Offset of the hitbox in relation to the entity position float default_offsetx; + /// Offset of the hitbox in relation to the entity position float default_offsety; + /// Half of the width of the hitbox float default_hitboxx; + /// Half of the height of the hitbox float default_hitboxy; SHAPE default_shape; bool default_hitbox_enabled; @@ -115,17 +119,13 @@ struct EntityDB EntityDB(const ENT_TYPE other); }; -using EntityMap = std::unordered_map; - struct EntityItem { std::string name; uint32_t id; EntityItem(const std::string& name_, uint32_t id_) - : name(name_), id(id_) - { - } + : name(name_), id(id_){}; bool operator<(const EntityItem& item) const { return id < item.id; @@ -147,10 +147,10 @@ struct EntityFactory EntityDB types[0x395]; bool type_set[0x395]; std::unordered_map> entity_instance_map; // game_unorderedmap probably - EntityMap entity_map; // game_unorderedmap probably + std::unordered_map entity_map; // game_unorderedmap probably }; -EntityDB* get_type(uint32_t id); +EntityDB* get_type(ENT_TYPE id); ENT_TYPE to_id(std::string_view id); @@ -158,4 +158,4 @@ std::string_view to_name(ENT_TYPE id); std::vector list_entities(); -struct EntityFactory* entity_factory(); +EntityFactory* entity_factory(); diff --git a/src/game_api/entity_lookup.cpp b/src/game_api/entity_lookup.cpp index dfcb2a354..ef2d41f75 100644 --- a/src/game_api/entity_lookup.cpp +++ b/src/game_api/entity_lookup.cpp @@ -163,7 +163,7 @@ std::vector get_entities_at(std::vector entity_types, uint32 { for (auto& item : entities.entities()) { - auto [ix, iy] = item->position(); + auto [ix, iy] = item->abs_position(); float distance = (float)std::sqrt(std::pow(x - ix, 2) + std::pow(y - iy, 2)); if (distance < radius && entity_type_check(proper_types, item->type->id)) { diff --git a/src/game_api/layer.cpp b/src/game_api/layer.cpp index 36c9c6645..7ab172fff 100644 --- a/src/game_api/layer.cpp +++ b/src/game_api/layer.cpp @@ -207,7 +207,7 @@ void Layer::move_grid_entity(Entity* ent, uint32_t x, uint32_t y, Layer* dest_la { if (ent) { - const auto pos = ent->position(); + const auto pos = ent->abs_position(); const uint32_t current_grid_x = static_cast(std::round(pos.x)); const uint32_t current_grid_y = static_cast(std::round(pos.y)); if (current_grid_x < g_level_max_x && current_grid_y < g_level_max_y) @@ -241,7 +241,7 @@ void Layer::destroy_grid_entity(Entity* ent) } } - const auto pos = ent->position(); + const auto pos = ent->abs_position(); const uint32_t current_grid_x = static_cast(std::round(pos.x)); const uint32_t current_grid_y = static_cast(std::round(pos.y)); if (current_grid_x < g_level_max_x && current_grid_y < g_level_max_y) diff --git a/src/game_api/movable.hpp b/src/game_api/movable.hpp index b6e1b86bf..b507b3b36 100644 --- a/src/game_api/movable.hpp +++ b/src/game_api/movable.hpp @@ -211,6 +211,6 @@ class Movable : public Entity virtual void v88(Entity* entity, float vecloty) = 0; // 88, on_ragdoll? - for player, triggers only when you throw him into wall/ground/celling virtual bool v89(void*, void*, bool, bool default_return_flipped) = 0; // 89, triggers on item_rubble?, first parameter only tested if it's 0 for punishball, ignored in the rest, second parameter never used (leftover?) virtual void on_crushed_by(Entity*) = 0; // 90, e.g. crushed by elevator, punishball, pushblock, crushtrap (not quillback or boulder) - virtual SoundMeta* on_fall_onto(uint32_t play_sound_id, Entity* fell_on_entity) = 0; // 91, plays the sfx at the entity and sets sound parameters + virtual SoundMeta* on_fall_onto(SOUNDID play_sound_id, Entity* fell_on_entity) = 0; // 91, plays the sfx at the entity and sets sound parameters virtual void on_instakill_death() = 0; // 92, seems to only trigger for enemies that die in one hit, creates some big struct on stack, feeds it to some unknown function }; diff --git a/src/game_api/rpc.cpp b/src/game_api/rpc.cpp index 663959a21..6ef647bd9 100644 --- a/src/game_api/rpc.cpp +++ b/src/game_api/rpc.cpp @@ -72,7 +72,7 @@ void attach_entity(Entity* overlay, Entity* attachee) attachee->overlay->remove_item(attachee, false); } - auto [x, y] = overlay->position(); + auto [x, y] = overlay->abs_position(); attachee->x -= x; attachee->y -= y; attachee->special_offsetx = attachee->x; @@ -102,17 +102,17 @@ int32_t attach_ball_and_chain(uint32_t uid, float off_x, float off_y) static const auto ball_entity_type = to_id("ENT_TYPE_ITEM_PUNISHBALL"); static const auto chain_entity_type = to_id("ENT_TYPE_ITEM_PUNISHCHAIN"); - auto [x, y, l] = get_position(uid); - auto* layer_ptr = State::get().layer(l); + auto pos = entity->abs_position(); + auto* layer_ptr = State::get().layer(entity->layer); - PunishBall* ball = (PunishBall*)layer_ptr->spawn_entity(ball_entity_type, x + off_x, y + off_y, false, 0.0f, 0.0f, false); + PunishBall* ball = (PunishBall*)layer_ptr->spawn_entity(ball_entity_type, pos.x + off_x, pos.y + off_y, false, 0.0f, 0.0f, false); ball->attached_to_uid = uid; const uint8_t chain_length = 15; for (uint8_t i = 0; i < chain_length; i++) { - StretchChain* chain = (StretchChain*)layer_ptr->spawn_entity(chain_entity_type, x, y, false, 0.0f, 0.0f, false); + StretchChain* chain = (StretchChain*)layer_ptr->spawn_entity(chain_entity_type, pos.x, pos.y, false, 0.0f, 0.0f, false); chain->animation_frame -= (i % 2); chain->at_end_of_chain_uid = ball->uid; @@ -144,6 +144,21 @@ void stack_entities(uint32_t bottom_uid, uint32_t top_uid, const float (&offset) } } +void teleport_entity_abs(Entity* ent, float dx, float dy, float vx, float vy) +{ + if (ent->overlay) + ent->overlay->remove_item(ent, false); + + ent->x = dx; + ent->y = dy; + if (ent->is_movable()) + { + auto movable_ent = ent->as(); + movable_ent->velocityx = vx; + movable_ent->velocityy = vy; + } +} + void move_entity_abs(uint32_t uid, float x, float y, float vx, float vy) { auto ent = get_entity_ptr(uid); @@ -155,7 +170,7 @@ void move_entity_abs(uint32_t uid, float x, float y, float vx, float vy) } else { - ent->teleport_abs(x, y, vx, vy); + teleport_entity_abs(ent, x, y, vx, vy); } } } @@ -173,7 +188,7 @@ void move_entity_abs(uint32_t uid, float x, float y, float vx, float vy, LAYER l } else { - ent->teleport_abs(offset.x + x, offset.y + y, vx, vy); + teleport_entity_abs(ent, offset.x + x, offset.y + y, vx, vy); ent->set_layer(layer); } } @@ -343,7 +358,10 @@ void entity_remove_item(uint32_t uid, uint32_t item_uid, std::optional che Entity* entity = get_entity_ptr(uid); if (entity == nullptr) return; - entity->remove_item_uid(item_uid, check_autokill.value_or(true)); + + auto entity_item = get_entity_ptr(item_uid); + if (entity_item) + entity->remove_item(entity_item, check_autokill.value_or(true)); } void lock_door_at(float x, float y) @@ -1215,7 +1233,11 @@ void move_grid_entity(int32_t uid, float x, float y, LAYER layer) Vec2 offset; const auto actual_layer = enum_to_layer(layer, offset); state.layer(entity->layer)->move_grid_entity(entity, offset.x + x, offset.y + y, state.layer(actual_layer)); - entity->teleport_abs(offset.x + x, offset.y + y, 0, 0); + + if (entity->overlay) + entity->overlay->remove_item(entity, false); + entity->x = offset.x + x; + entity->y = offset.y + y; entity->set_layer(layer); } } diff --git a/src/game_api/script/lua_vm.cpp b/src/game_api/script/lua_vm.cpp index e80a7a964..2154888fe 100644 --- a/src/game_api/script/lua_vm.cpp +++ b/src/game_api/script/lua_vm.cpp @@ -1140,11 +1140,41 @@ end lua["screen_distance"] = screen_distance; /// Get position `x, y, layer` of entity by uid. Use this, don't use `Entity.x/y` because those are sometimes just the offset to the entity /// you're standing on, not real level coordinates. - lua["get_position"] = get_position; + lua["get_position"] = [](int32_t uid) -> std::tuple + { + Entity* ent = get_entity_ptr(uid); + if (ent) + { + auto pos = ent->abs_position(); + return {pos.x, pos.y, ent->layer}; + } + return {}; + }; /// Get interpolated render position `x, y, layer` of entity by uid. This gives smooth hitboxes for 144Hz master race etc... - lua["get_render_position"] = get_render_position; - /// Get velocity `vx, vy` of an entity by uid. Use this, don't use `Entity.velocityx/velocityy` because those are relative to `Entity.overlay`. - lua["get_velocity"] = get_velocity; + lua["get_render_position"] = [](int32_t uid) -> std::tuple + { + Entity* ent = get_entity_ptr(uid); + if (ent) + { + if (ent->rendering_info != nullptr && !ent->rendering_info->render_inactive) + return std::make_tuple(ent->rendering_info->x, ent->rendering_info->y, ent->layer); + else + { + auto pos = ent->abs_position(); + return {pos.x, pos.y, ent->layer}; + } + } + return {}; + }; + /// Get velocity `vx, vy` of an entity by uid. Use this to get velocity relative to the game world, (the `Entity.velocityx/velocityy` are relative to `Entity.overlay`). Only works for movable or liquid entities + lua["get_velocity"] = [](int32_t uid) -> std::tuple + { + Entity* ent = get_entity_ptr(uid); + if (ent) + return ent->get_absolute_velocity(); + + return {}; + }; /// Remove item by uid from entity. `check_autokill` defaults to true, checks if entity should be killed when missing overlay and kills it if so (can help with avoiding crashes) lua["entity_remove_item"] = entity_remove_item; /// Spawns and attaches ball and chain to `uid`, the initial position of the ball is at the entity position plus `off_x`, `off_y` @@ -1263,7 +1293,7 @@ end if (ea == nullptr || eb == nullptr) return -1.0f; else - return (float)std::sqrt(std::pow(ea->position().x - eb->position().x, 2) + std::pow(ea->position().y - eb->position().y, 2)); + return (float)std::sqrt(std::pow(ea->abs_position().x - eb->abs_position().x, 2) + std::pow(ea->abs_position().y - eb->abs_position().y, 2)); }; /// Basically gets the absolute coordinates of the area inside the unbreakable bedrock walls, from wall to wall. Every solid entity should be /// inside these boundaries. The order is: left x, top y, right x, bottom y @@ -1741,11 +1771,11 @@ end /// Check [strings00_hashed.str](https://github.com/spelunky-fyi/overlunky/blob/main/docs/game_data/strings00_hashed.str) for the hash values, or extract assets with modlunky and check those. lua["hash_to_stringid"] = hash_to_stringid; - /// Get string behind STRINGID, don't use stringid directly for vanilla string, use [hash_to_stringid](#hash_to_stringid) first + /// Get string behind STRINGID, **don't use stringid directly for vanilla string**, use [hash_to_stringid](#hash_to_stringid) first /// Will return the string of currently choosen language lua["get_string"] = get_string; - /// Change string at the given id (don't use stringid diretcly for vanilla string, use `hash_to_stringid` first) + /// Change string at the given id (**don't use stringid directly for vanilla string**, use [hash_to_stringid](#hash_to_stringid) first) /// This edits custom string and in game strings but changing the language in settings will reset game strings lua["change_string"] = [](STRINGID id, std::u16string str) { @@ -1783,7 +1813,7 @@ end /// ENT_TYPE_ITEM_PICKUP_SPIKESHOES, ENT_TYPE_ITEM_PICKUP_SPRINGSHOES, ITEM_MACHETE, ITEM_BOOMERANG, ITEM_CROSSBOW, ITEM_SHOTGUN, ITEM_FREEZERAY, ITEM_WEBGUN, ITEM_CAMERA, ITEM_MATTOCK, ITEM_PURCHASABLE_JETPACK, ITEM_PURCHASABLE_HOVERPACK, /// ITEM_TELEPORTER, ITEM_PURCHASABLE_TELEPORTER_BACKPACK, ITEM_PURCHASABLE_POWERPACK}
/// Min 6, Max 255, if you want less then 6 you need to write some of them more then once (they will have higher "spawn chance"). - /// If you use this function in the level with diceshop in it, you have to update `item_ids` in the [ITEM_DICE_PRIZE_DISPENSER](#PrizeDispenser). + /// If you use this function in the level with dice shop in it, you have to update `item_ids` in the [ITEM_DICE_PRIZE_DISPENSER](#PrizeDispenser). /// Use empty table as argument to reset to the game default lua["change_diceshop_prizes"] = change_diceshop_prizes; @@ -2234,7 +2264,7 @@ end /// Look at the example on how to mimic game layer switching behavior lua["set_camera_layer_control_enabled"] = set_camera_layer_control_enabled; - /// Set multiplier (default 1.0) for a QueryPerformanceCounter hook based speedhack, similar to the one in Cheat Engine. Call without arguments to reset. Also see set_frametime + /// Set multiplier (default 1.0) for a QueryPerformanceCounter hook based speedhack, similar to the one in Cheat Engine. Call without arguments to reset. Also see [set_frametime](#set_frametime) lua["set_speedhack"] = set_speedhack; /// Get the current speedhack multiplier @@ -2261,7 +2291,7 @@ end /// Initializes some adventure run related values and loads the character select screen, as if starting a new adventure run from the Play menu. Character select can be skipped by changing `state.screen_next` right after calling this function, maybe with `warp()`. If player isn't already selected, make sure to set `state.items.player_select` and `state.items.player_count` appropriately too. lua["play_adventure"] = init_adventure; - /// Initializes some seedeed run related values and loads the character select screen, as if starting a new seeded run after entering the seed. + /// Initializes some seeded run related values and loads the character select screen, as if starting a new seeded run after entering the seed. lua["play_seeded"] = init_seeded; /// Change layer at which the liquid spawns in, THIS FUNCTION NEEDS TO BE CALLED BEFORE THE LEVEL IS BUILD, otherwise collisions and other stuff will be wrong for the newly spawned liquid @@ -2572,7 +2602,7 @@ end // Params: int x, int y, ROOM_TEMPLATE room_template, PreHandleRoomTilesContext room_ctx // Return: `bool last_callback` to determine whether callbacks of the same type should be executed after this // Runs after a random room was selected and right before it would spawn entities for each tile code - // Allows you to modify the rooms content in the front and back layer as well as add a backlayer if not yet existant + // Allows you to modify the rooms content in the front and back layer as well as add a back layer if not yet existant // SAVE // Params: SaveContext save_ctx // Runs at the same times as ON.SCREEN, but receives the save_ctx @@ -2581,7 +2611,7 @@ end // Runs as soon as your script is loaded, including reloads, then never again // RENDER_PRE_GAME // Params: VanillaRenderContext render_ctx - // Runs before the ingame part of the game is rendered. Return `true` to skip rendering. + // Runs before the in-game part of the game is rendered. Return `true` to skip rendering. // RENDER_POST_GAME // Params: VanillaRenderContext render_ctx // Runs after the level and HUD are rendered, before pause menus and blur effects diff --git a/src/game_api/script/usertypes/entities_items_lua.cpp b/src/game_api/script/usertypes/entities_items_lua.cpp index 979355ac5..fc15183b8 100644 --- a/src/game_api/script/usertypes/entities_items_lua.cpp +++ b/src/game_api/script/usertypes/entities_items_lua.cpp @@ -155,11 +155,21 @@ void register_usertypes(sol::state& lua) lua.new_usertype( "Purchasable", + "acquire", + &Purchasable::acquire, sol::base_classes, sol::bases()); lua.new_usertype( "DummyPurchasableEntity", + "replace_entity", + &DummyPurchasableEntity::replace_entity, + "exploding", + &DummyPurchasableEntity::exploding, + "explosion_timer", + &DummyPurchasableEntity::explosion_timer, + "trigger_explosion", + &DummyPurchasableEntity::trigger_explosion, sol::base_classes, sol::bases()); @@ -183,6 +193,8 @@ void register_usertypes(sol::state& lua) &Jetpack::flame_on, "fuel", &Jetpack::fuel, + "acceleration", + &Jetpack::acceleration, sol::base_classes, sol::bases()); @@ -635,6 +647,8 @@ void register_usertypes(sol::state& lua) &OlmecCannon::timer, "bombs_left", &OlmecCannon::bombs_left, + "spawn_projectile", + &OlmecCannon::spawn_projectile, sol::base_classes, sol::bases()); diff --git a/src/game_api/script/usertypes/entities_monsters_lua.cpp b/src/game_api/script/usertypes/entities_monsters_lua.cpp index ecd3a4440..fe0aa22e9 100644 --- a/src/game_api/script/usertypes/entities_monsters_lua.cpp +++ b/src/game_api/script/usertypes/entities_monsters_lua.cpp @@ -145,6 +145,12 @@ void register_usertypes(sol::state& lua) &RoomOwner::aggro_trigger, "was_hurt", &RoomOwner::was_hurt, + "should_attack_on_sight", + &RoomOwner::should_attack_on_sight, + "is_angry_flag_set", + &RoomOwner::is_angry_flag_set, + "weapon_type", + &RoomOwner::weapon_type, sol::base_classes, sol::bases()); @@ -169,6 +175,10 @@ void register_usertypes(sol::state& lua) &NPC::ai_state, "aggro", &NPC::aggro, + "should_attack_on_sight", + &NPC::should_attack_on_sight, + "weapon_type", + &NPC::weapon_type, sol::base_classes, sol::bases()); @@ -280,6 +290,8 @@ void register_usertypes(sol::state& lua) &Spider::jump_timer, "trigger_distance", &Spider::trigger_distance, + "on_ceiling", + &Spider::on_ceiling, sol::base_classes, sol::bases()); diff --git a/src/game_api/script/usertypes/entities_mounts_lua.cpp b/src/game_api/script/usertypes/entities_mounts_lua.cpp index ac59fea45..7e1ef335e 100644 --- a/src/game_api/script/usertypes/entities_mounts_lua.cpp +++ b/src/game_api/script/usertypes/entities_mounts_lua.cpp @@ -48,6 +48,20 @@ void register_usertypes(sol::state& lua) &Mount::carry, "tame", &Mount::tame, + "get_rider_offset", + &Mount::get_rider_offset, + "get_rider_offset_crouching", + &Mount::get_rider_offset_crouching, + "get_jump_sound", + &Mount::get_jump_sound, + "get_attack_sound", + &Mount::get_attack_sound, + "get_mounting_sound", + &Mount::get_mounting_sound, + "get_walking_sound", + &Mount::get_walking_sound, + "get_untamed_loop_sound", + &Mount::get_untamed_loop_sound, sol::base_classes, sol::bases()); diff --git a/src/game_api/script/usertypes/entity_lua.cpp b/src/game_api/script/usertypes/entity_lua.cpp index 9c71924ad..5ee943879 100644 --- a/src/game_api/script/usertypes/entity_lua.cpp +++ b/src/game_api/script/usertypes/entity_lua.cpp @@ -210,17 +210,11 @@ void register_usertypes(sol::state& lua) // entity_type["abs_x"] = &Entity::abs_x; /// NoDoc entity_type["abs_x"] = sol::property([](Entity& e) -> float - { - if (e.abs_x == -FLT_MAX) - return e.position().x; - return e.abs_x; }); + { return e.abs_position().x; }); // entity_type["abs_y"] = &Entity::abs_y; /// NoDoc entity_type["abs_y"] = sol::property([](Entity& e) -> float - { - if (e.abs_y == -FLT_MAX) - return e.position().y; - return e.abs_y; }); + { return e.abs_position().y; }); entity_type["layer"] = &Entity::layer; entity_type["width"] = &Entity::w; entity_type["height"] = &Entity::h; @@ -279,6 +273,8 @@ void register_usertypes(sol::state& lua) entity_type["flip"] = &Entity::flip; entity_type["remove_item"] = &Entity::remove_item; entity_type["apply_db"] = &Entity::apply_db; + entity_type["get_absolute_velocity"] = &Entity::get_absolute_velocity; + entity_type["get_hitbox"] = &Entity::get_hitbox; /* Entity // user_data diff --git a/src/game_api/script/usertypes/hitbox_lua.cpp b/src/game_api/script/usertypes/hitbox_lua.cpp index 82d670826..2b5e95037 100644 --- a/src/game_api/script/usertypes/hitbox_lua.cpp +++ b/src/game_api/script/usertypes/hitbox_lua.cpp @@ -30,14 +30,20 @@ void register_usertypes(sol::state& lua) /// Gets the hitbox of an entity, use `extrude` to make the hitbox bigger/smaller in all directions and `offset` to offset the hitbox in a given direction lua["get_hitbox"] = [](uint32_t uid, sol::optional extrude, sol::optional offsetx, sol::optional offsety) -> AABB { - auto [sx1, sy1, sx2, sy2] = get_hitbox(uid, false); - return fixup_hitbox(AABB{sx1, sy1, sx2, sy2}, extrude, offsetx, offsety); + AABB hitbox; + if (auto ent = get_entity_ptr(uid)) + hitbox = ent->get_hitbox(false); + + return fixup_hitbox(hitbox, extrude, offsetx, offsety); }; /// Same as `get_hitbox` but based on `get_render_position` lua["get_render_hitbox"] = [](uint32_t uid, sol::optional extrude, sol::optional offsetx, sol::optional offsety) -> AABB { - auto [sx1, sy1, sx2, sy2] = get_hitbox(uid, true); - return fixup_hitbox(AABB{sx1, sy1, sx2, sy2}, extrude, offsetx, offsety); + AABB hitbox; + if (auto ent = get_entity_ptr(uid)) + hitbox = ent->get_hitbox(true); + + return fixup_hitbox(hitbox, extrude, offsetx, offsety); }; /// Convert an `AABB` to a screen `AABB` that can be directly passed to draw functions lua["screen_aabb"] = [](AABB box) -> AABB diff --git a/src/game_api/script/usertypes/sound_lua.cpp b/src/game_api/script/usertypes/sound_lua.cpp index 29976615a..76bc3b4a4 100644 --- a/src/game_api/script/usertypes/sound_lua.cpp +++ b/src/game_api/script/usertypes/sound_lua.cpp @@ -168,6 +168,8 @@ void register_usertypes(sol::state& lua, SoundManager* sound_manager) &SoundMeta::x, "y", &SoundMeta::y, + "sound_info", + &SoundMeta::sound_info, "left_channel", //&SoundMeta::left_channel, sol::property([](SoundMeta* sm) @@ -179,15 +181,38 @@ void register_usertypes(sol::state& lua, SoundManager* sound_manager) "start_over", &SoundMeta::start_over, "playing", - &SoundMeta::playing); + &SoundMeta::playing, + "start", + &SoundMeta::start); lua.new_usertype( "BackgroundSound", sol::base_classes, sol::bases()); + lua.new_usertype( + "SoundInfo", + "sound_id", + sol::readonly(&SoundInfo::sound_id), + "sound_name", + sol::property([](SoundInfo& si) // -> VANILLA_SOUND + { return si.sound_name /**/; })); // return copy, so it's read only + + auto play_sound = sol::overload(static_cast(::play_sound), static_cast(::play_sound)); + + /// Use source_uid to make the sound be played at the location of that entity, set it -1 to just play it "everywhere" + /// Returns SoundMeta, beware that the sound can't be stopped (`start_over` and `playing` are unavailable). Should only be used for sfx. lua["play_sound"] = play_sound; + // lua["convert_sound_id"] = convert_sound_id; + /// NoDoc + lua["convert_sound_id"] = sol::overload([](SOUNDID id) -> const VANILLA_SOUND& + { auto back_end = LuaBackend::get_calling_backend(); + return back_end->sound_manager->convert_sound_id(id); }, + [](VANILLA_SOUND sound) -> SOUNDID + {auto back_end = LuaBackend::get_calling_backend(); + return back_end->sound_manager->convert_sound_id(sound); }); + /// Third parameter to `CustomSound:play()`, specifies which group the sound will be played in and thus how the player controls its volume lua.create_named_table("SOUND_TYPE", "SFX", 0, "MUSIC", 1); /// Paramater to `PlayingSound:set_looping()`, specifies what type of looping this sound should do diff --git a/src/game_api/search.cpp b/src/game_api/search.cpp index 98c7474a7..d83b5cd38 100644 --- a/src/game_api/search.cpp +++ b/src/game_api/search.cpp @@ -713,8 +713,7 @@ std::unordered_map g_address_rules{ .at_exe(), }, { - "fmod_event_map"sv, // probably wrong - // Find a call to FMOD::Studio::System::getEvent (should be before the call to FMOD::Studio::EventDescription::getParameterDescriptionByName) + "fmod_event_map"sv, // Find a call to FMOD::Studio::System::getEvent (should be before the call to FMOD::Studio::EventDescription::getParameterDescriptionByName) // The third parameter is an event-pointer-pointer, the second parameter to the enclosing function is the event-id and will be used further down // to emplace a struct in an unordered_map (as seen by the strings inside the emplace function), that unordered_map is a global of type EventMap PatternCommandBuffer{} @@ -1923,7 +1922,7 @@ std::unordered_map g_address_rules{ }, { // Go into jetpack 99 virtual function (play_warning_sound), there are two calls for virtuls and one call to static function, that's the one - "play_sound"sv, + "play_sfx"sv, PatternCommandBuffer{} .find_inst("\x48\x83\xC1\x18\x41\xB8\x38\x01\x00\x00"sv) .at_exe() diff --git a/src/game_api/sound_manager.cpp b/src/game_api/sound_manager.cpp index e2de5e057..db4212a8c 100644 --- a/src/game_api/sound_manager.cpp +++ b/src/game_api/sound_manager.cpp @@ -7,11 +7,11 @@ #include // for remove_if, unique_ptr #include // for lock_guard, mutex -#include "entity.hpp" // -#include "logger.h" // for DEBUG -#include "overloaded.hpp" // for overloaded -#include "script/lua_backend.hpp" // -#include "search.hpp" // for get_address +#include "aliases.hpp" // +#include "entity.hpp" // +#include "logger.h" // for DEBUG +#include "overloaded.hpp" // for overloaded +#include "search.hpp" // for get_address #define SOL_ALL_SAFETIES_ON 1 @@ -871,61 +871,73 @@ bool SoundManager::set_parameter(PlayingSound playing_sound, VANILLA_SOUND_PARAM playing_sound.m_FmodHandle); } -int32_t sound_name_to_id(const VANILLA_SOUND s_name) +SOUNDID SoundManager::convert_sound_id(const VANILLA_SOUND& s_name) { - static std::vector sound_names; - if (sound_names.empty()) - { - auto sound_mgr = LuaBackend::get_calling_backend()->sound_manager; - sound_mgr->for_each_event_name( - [](std::string event_name) - { - sound_names.push_back(std::move(event_name)); - }); - } + for (auto& [id, event_descr] : *m_SoundData.Events) + if (event_descr.Name == s_name) + return id; - for (auto& sound : sound_names) - { - if (sound == s_name) - { - return int32_t(&sound - &sound_names[0]) + 1; - } - } return -1; } -SoundMeta* play_sound_by_id(uint32_t sound_id, uint32_t source_uid) +const VANILLA_SOUND& SoundManager::convert_sound_id(SOUNDID sound_id) +{ + static const VANILLA_SOUND empty{}; + // auto event = m_SoundData.Events->find(id); // didn't work for some reason + // if (event == m_SoundData.Events->end()) + // return empty; + // return event->second.Name; + if (sound_id < 0) + return empty; + + for (auto& [id, event_descr] : *m_SoundData.Events) + if (id == (uint32_t)sound_id) + return event_descr.Name; + + return empty; +} + +SoundMeta* play_sound(SOUNDID sound_id, uint32_t source_uid) { if (sound_id == -1) return nullptr; using play_sound = SoundMeta*(int32_t); - static auto play_sound_func = (play_sound*)get_address("play_sound"); + static auto play_sound_func = (play_sound*)get_address("play_sfx"); Entity* source = get_entity_ptr(source_uid); SoundMeta* sound_info{nullptr}; - if (source_uid == ~0 || source != nullptr) // don't play the sound if the entity is not valid + if (source_uid == ~0 || source) // don't play the sound if the entity is not valid but allow -1 { sound_info = play_sound_func(sound_id); - if (source != nullptr) + if (source && sound_info) source->set_as_sound_source(sound_info); } return sound_info; } +SoundManager* g_sound_manager{nullptr}; + SoundMeta* play_sound(VANILLA_SOUND sound, uint32_t source_uid) { - auto sound_id = sound_name_to_id(sound); - return play_sound_by_id(sound_id, source_uid); + if (g_sound_manager == nullptr) + g_sound_manager = new SoundManager(nullptr); + + auto sound_id = g_sound_manager->convert_sound_id(sound); + return play_sound(sound_id, source_uid); } SoundMeta* construct_soundmeta(VANILLA_SOUND sound, bool background_sound) { - return construct_soundmeta(sound_name_to_id(sound), background_sound); + if (g_sound_manager == nullptr) + g_sound_manager = new SoundManager(nullptr); + + auto sound_id = g_sound_manager->convert_sound_id(sound); + return construct_soundmeta(sound_id, background_sound); } -SoundMeta* construct_soundmeta(uint32_t sound_id, bool background_sound) +SoundMeta* construct_soundmeta(SOUNDID sound_id, bool background_sound) { using construct_soundposition_ptr_fun_t = SoundMeta*(uint32_t id, bool background_sound); static const auto construct_soundposition_ptr_call = (construct_soundposition_ptr_fun_t*)get_address("construct_soundmeta"); diff --git a/src/game_api/sound_manager.hpp b/src/game_api/sound_manager.hpp index 4c9d1c66d..230e2bfd4 100644 --- a/src/game_api/sound_manager.hpp +++ b/src/game_api/sound_manager.hpp @@ -173,6 +173,8 @@ class SoundManager fun(parameter_name, static_cast(i)); } } + SOUNDID convert_sound_id(const VANILLA_SOUND& s_name); + const VANILLA_SOUND& convert_sound_id(SOUNDID id); private: bool m_IsInit{false}; @@ -255,9 +257,9 @@ class SoundManager struct SoundInfo { int64_t unknown1; - uint32_t sound_id; - int32_t unknown2; // padding probably - std::string sound_name; // not 100% sure if it's standard + SOUNDID sound_id; + int32_t unknown2; // padding probably + std::string sound_name; }; // there is actually base class that consists of up to the left/right channel, used for the sfx @@ -297,12 +299,15 @@ struct BackgroundSound : public SoundMeta bool destroy_sound; // don't use directly, use the kill function }; -/// Use source_uid to make the sound be played at the location of that entity, set it -1 to just play it "everywhere" -/// Returns SoundMeta (read only), beware that after the sound starts, that memory is no longer valid SoundMeta* play_sound(VANILLA_SOUND sound, uint32_t source_uid); -SoundMeta* play_sound_by_id(uint32_t sound_id, uint32_t source_uid); +SoundMeta* play_sound(SOUNDID sound_id, uint32_t source_uid); // could probably be exposed if someone can actually figure out how to properly "register it"? // it also needs to make sure the lua owns the returned object and it will properly delete it SoundMeta* construct_soundmeta(VANILLA_SOUND sound, bool background_sound); -SoundMeta* construct_soundmeta(uint32_t sound_id, bool background_sound); +SoundMeta* construct_soundmeta(SOUNDID sound_id, bool background_sound); +/* +VANILLA_SOUND convert_sound_id(SOUNDID id); // for the autodoc +/// Convert SOUNDID to VANILLA_SOUND and vice versa +SOUNDID convert_sound_id(VANILLA_SOUND sound); +*/ diff --git a/src/game_api/spawn_api.cpp b/src/game_api/spawn_api.cpp index 556f351b8..c7cd43296 100644 --- a/src/game_api/spawn_api.cpp +++ b/src/game_api/spawn_api.cpp @@ -330,7 +330,7 @@ int32_t spawn_tree(float x, float y, LAYER layer, uint16_t height) if (left) deco->flags |= 1U << 16; // flag 17: facing left }; - auto test_pos = current_piece->position(); + auto test_pos = current_piece->abs_position(); if (static_cast(test_pos.x) + 1 < g_level_max_x && layer_ptr->get_grid_entity_at(test_pos.x + 1, test_pos.y) == nullptr && prng.random_chance(2, PRNG::PRNG_CLASS::ENTITY_VARIATION)) @@ -543,7 +543,7 @@ void fix_impostor_lake_positions() for (auto& lake : state->liquid_physics->impostor_lakes) { Entity* impostor_lake = lake.impostor_lake; - auto [x_pos, y_pos] = impostor_lake->position(); + auto [x_pos, y_pos] = impostor_lake->abs_position(); x_pos += impostor_lake->offsetx; y_pos += impostor_lake->offsety; float hitboxx = impostor_lake->hitboxx; diff --git a/src/game_api/state.cpp b/src/game_api/state.cpp index 31839f977..c6f57dcef 100644 --- a/src/game_api/state.cpp +++ b/src/game_api/state.cpp @@ -823,7 +823,7 @@ uint8_t enum_to_layer(const LAYER layer, Vec2& player_position) auto player = state->items->player(static_cast(std::abs((int)layer) - 1)); if (player != nullptr) { - player_position = player->position(); + player_position = player->abs_position(); return player->layer; } } diff --git a/src/injected/ui.cpp b/src/injected/ui.cpp index 95a3bdffc..b7d578e2f 100644 --- a/src/injected/ui.cpp +++ b/src/injected/ui.cpp @@ -1334,13 +1334,13 @@ void smart_delete(Entity* ent, bool unsafe = false) UI::safe_destroy(ent, unsafe); if ((ent->type->id >= first_door && ent->type->id <= first_door + 15) || ent->type->id == logical_door) { - auto pos = ent->position(); + auto pos = ent->abs_position(); auto layer = (LAYER)ent->layer; UI::cleanup_at(pos.x, pos.y, layer, ent->type->id); } if (ent->type->search_flags & 0x180) { - auto pos = ent->position(); + auto pos = ent->abs_position(); auto layer = (LAYER)ent->layer; ENT_TYPE type = ent->type->id; fix_decorations_at(std::round(pos.x), std::round(pos.y), layer); @@ -1906,13 +1906,13 @@ void force_cheats() { for (auto ent : g_players) { - auto player = (Movable*)(ent->topmost_mount()); + auto player = ent->topmost_mount()->as(); if (player->overlay) { if (player->state == 6 && (player->movex != 0 || player->movey != 0)) { auto [x, y] = UI::get_position(player); - player->teleport_abs(x + player->movex * 0.3f, y + player->movey * 0.07f, 0, 0); + UI::teleport_entity_abs(player, x + player->movex * 0.3f, y + player->movey * 0.07f, 0, 0); } else player->overlay->remove_item(player, false); @@ -1928,7 +1928,7 @@ void force_cheats() auto cpos = UI::get_position(player); if (fix_co_coordinates(cpos)) { - player->teleport_abs(cpos.first, cpos.second, player->velocityx, player->velocityy); + UI::teleport_entity_abs(player, cpos.first, cpos.second, player->velocityx, player->velocityy); } } } @@ -2104,7 +2104,7 @@ void clear_void() for (auto uid : UI::get_entities_by({}, 1422, LAYER::FRONT)) { auto ent = get_entity_ptr(uid); - auto [x, y] = ent->position(); + auto [x, y] = ent->abs_position(); if (x > 2.5f && y < 122.5f && x < g_state->w * 10.0f + 2.5f && y > 122.5f - g_state->h * 8.0f) UI::safe_destroy(ent); } @@ -2118,7 +2118,7 @@ void load_void(std::string data) VoidData v; sscanf_s(data.c_str(), "V1%02X%02X", &v.x, &v.y); g_players = UI::get_players(); - g_players[0]->teleport_abs((float)v.x, (float)v.y, 0, 0); + UI::teleport_entity_abs(g_players[0], (float)v.x, (float)v.y, 0, 0); std::string ents = data.substr(6); if (ents.size() > 0) @@ -2191,7 +2191,7 @@ void import_void() std::string serialize_void() { const int export_mask = 398; - auto [px, py] = g_players[0]->position(); + auto [px, py] = g_players[0]->abs_position(); std::string v = fmt::format("V1{:02X}{:02X}", (uint8_t)(px + 0.5f), (uint8_t)(py + 0.5f)); auto uids = g_selected_ids; if (uids.empty()) @@ -2201,7 +2201,7 @@ std::string serialize_void() auto ent = get_entity_ptr(uid); if (!ent || !(ent->type->search_flags & export_mask)) continue; - auto [x, y] = ent->position(); + auto [x, y] = ent->abs_position(); if ((!ent->overlay || (ent->x != 0 || ent->y != 0)) && x > 2.5f && y < 122.5f && x < g_state->w * 10.0f + 2.5f && y > 122.5f - g_state->h * 8.0f) { char buf[4]; @@ -3393,7 +3393,7 @@ bool process_keys(UINT nCode, WPARAM wParam, [[maybe_unused]] LPARAM lParam) auto layer_to = LAYER::FRONT; if (g_players.at(0)->layer == 0) layer_to = LAYER::BACK; - g_players.at(0)->set_layer(layer_to); + g_players.at(0)->topmost_mount()->set_layer(layer_to); if (layer_to == LAYER::BACK || !g_state->illumination) { g_players.at(0)->emitted_light->enabled = true; @@ -5397,7 +5397,7 @@ void render_clickhandler() if (g_state->theme == 10) fix_co_coordinates(cpos); auto player = (Movable*)g_players.at(0)->topmost_mount(); - player->teleport_abs(cpos.first, cpos.second, g_vx, g_vy); + UI::teleport_entity_abs(player, cpos.first, cpos.second, g_vx, g_vy); g_x = 0; g_y = 0; g_vx = 0; @@ -5411,7 +5411,7 @@ void render_clickhandler() if (g_state->theme == 10) fix_co_coordinates(cpos); auto player = (Movable*)g_players.at(0)->topmost_mount(); - player->teleport_abs(cpos.first, cpos.second, g_vx, g_vy); + UI::teleport_entity_abs(player, cpos.first, cpos.second, g_vx, g_vy); g_x = 0; g_y = 0; g_vx = 0; @@ -7670,7 +7670,7 @@ void render_entity_props(int uid, bool detached = false) auto layer_to = LAYER::FRONT; if (entity->layer == 0) layer_to = LAYER::BACK; - entity->set_layer(layer_to); + entity->topmost_mount()->set_layer(layer_to); } ImGui::SameLine(); switch (entity->layer) @@ -7742,8 +7742,8 @@ void render_entity_props(int uid, bool detached = false) if (render_uid(ent->uid, "EntityItems", true)) removed_uid = ent->uid; } - if (removed_uid) - entity_pow->remove_item_uid(removed_uid, true); + if (auto removed = get_entity_ptr(removed_uid)) + entity_pow->remove_item(removed, true); ImGui::SeparatorText("Powerups"); int removed_powerup = 0; for (const auto& [powerup_id, powerup_entity] : entity_pow->powerups) @@ -7823,8 +7823,8 @@ void render_entity_props(int uid, bool detached = false) if (render_uid(ent->uid, "EntityItems", true)) removed_uid = ent->uid; } - if (removed_uid) - entity->remove_item_uid(removed_uid, true); + if (auto removed = get_entity_ptr(removed_uid)) + entity->remove_item(removed, true); } endmenu(); } diff --git a/src/injected/ui_util.cpp b/src/injected/ui_util.cpp index 8be35fc2a..c4ea81d68 100644 --- a/src/injected/ui_util.cpp +++ b/src/injected/ui_util.cpp @@ -92,6 +92,64 @@ float UI::get_zoom_level() auto game_api = GameAPI::get(); return game_api->get_current_zoom(); } +void teleport_entity(Entity* ent, float dx, float dy, bool s, float vx, float vy, bool snap) +{ + if (ent->overlay) + ent->overlay->remove_item(ent, false); + + auto topmost = ent->topmost_mount(); // we just detached from overlay, so this is kind of pointelss + if (!s) + { + auto [x_pos, y_pos] = topmost->abs_position(); + // player relative coordinates + x_pos += dx; + y_pos += dy; + if (snap) + { + x_pos = round(x_pos); + y_pos = round(y_pos); + } + topmost->x = x_pos; + topmost->y = y_pos; + } + else + { + // screen coordinates -1..1 + // log::debug!("Teleporting to screen {}, {}", x, y); + auto& state = State::get(); + auto [x_pos, y_pos] = state.click_position(dx, dy); + if (snap && abs(vx) + abs(vy) <= 0.04f) + { + x_pos = round(x_pos); + y_pos = round(y_pos); + } + // log::debug!("Teleporting to {}, {}", x, y); + topmost->x = x_pos; + topmost->y = y_pos; + } + // set velocity + if (topmost->is_movable()) + { + auto movable_ent = topmost->as(); + movable_ent->velocityx = vx; + movable_ent->velocityy = vy; + } + return; +} +void UI::teleport_entity_abs(Entity* ent, float dx, float dy, float vx, float vy) +{ + if (ent->overlay) + ent->overlay->remove_item(ent, false); + + ent->x = dx; + ent->y = dy; + if (ent->is_movable()) + { + auto movable_ent = ent->as(); + movable_ent->velocityx = vx; + movable_ent->velocityy = vy; + } +} void UI::teleport(float x, float y, bool s, float vx, float vy, bool snap) { auto state = State::get().ptr_main(); @@ -99,7 +157,7 @@ void UI::teleport(float x, float y, bool s, float vx, float vy, bool snap) auto player = state->items->player(0); if (player == nullptr) return; - player->teleport(x, y, s, vx, vy, snap); + teleport_entity(player, x, y, s, vx, vy, snap); } std::pair UI::screen_position(float x, float y) { @@ -140,7 +198,7 @@ Entity* UI::get_entity_at(float x, float y, bool s, float radius, uint32_t mask) float current_distance = radius; auto check_distance = [¤t_entity, ¤t_distance, &x, &y](Entity* test_entity) { - const auto [ix, iy] = test_entity->position(); + const auto [ix, iy] = test_entity->abs_position(); const float distance = (float)std::sqrt(std::pow(x - ix, 2) + std::pow(y - iy, 2)); if (distance < current_distance) { @@ -180,7 +238,7 @@ void UI::move_entity(uint32_t uid, float x, float y, bool s, float vx, float vy, { auto ent = get_entity_ptr(uid); if (ent) - ent->teleport(x, y, s, vx, vy, snap); + teleport_entity(ent, x, y, s, vx, vy, snap); } SaveData* UI::savedata() { @@ -234,7 +292,7 @@ std::pair UI::get_position(Entity* ent, bool render) return {.0f, .0f}; if (!render) - return ent->position(); + return ent->abs_position(); if (ent->rendering_info && !ent->rendering_info->render_inactive) return {ent->rendering_info->x, ent->rendering_info->y}; @@ -246,7 +304,7 @@ std::pair UI::get_position(Entity* ent, bool render) return {ent_item->rendering_info->x - ent_item->x, ent_item->rendering_info->y - ent_item->y}; } } - return ent->position(); + return ent->abs_position(); } bool UI::has_active_render(Entity* ent) { diff --git a/src/injected/ui_util.hpp b/src/injected/ui_util.hpp index 2964ef594..512ebaf16 100644 --- a/src/injected/ui_util.hpp +++ b/src/injected/ui_util.hpp @@ -101,4 +101,5 @@ class UI static void copy_state(int from, int to); static StateMemory* get_save_state(int slot); static void set_camera_layer_control_enabled(bool enable); + static void teleport_entity_abs(Entity* ent, float dx, float dy, float vx, float vy); }; From edd94cbfbcf1c88fc662c1fed36edda236db6b9f Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sun, 29 Sep 2024 18:35:22 +0200 Subject: [PATCH 10/21] add and improve entity attach/detach --- docs/game_data/spel2.lua | 2 + docs/src/includes/_types.md | 2 + src/game_api/entities_activefloors.cpp | 7 +-- src/game_api/entity.hpp | 19 +++++++++ src/game_api/entity_db.cpp | 4 +- src/game_api/layer.cpp | 12 ++++-- src/game_api/layer.hpp | 10 ++--- src/game_api/movable.hpp | 20 ++++----- src/game_api/rpc.cpp | 45 ++++++++++---------- src/game_api/script/usertypes/entity_lua.cpp | 2 + src/game_api/search.cpp | 4 +- src/injected/ui.cpp | 34 ++++----------- src/injected/ui_util.cpp | 8 ++-- 13 files changed, 88 insertions(+), 81 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index 879ca2188..9d4a0de26 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -2561,6 +2561,8 @@ function PRNG:random(min, max) end ---@field apply_db fun(self): nil @Applies changes made in `entity.type` ---@field get_absolute_velocity fun(self): Vec2 @Get's the velocity relative to the game world, only for movable or liquid entities ---@field get_hitbox fun(self, use_render_pos: boolean?): AABB @`use_render_pos` default is `false` + ---@field attach fun(self, new_overlay: Entity): nil @Attach to other entity (at the current relative postion to it) + ---@field detach fun(self, check_autokill: boolean?): nil @Detach from overlay ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 989461625..21ec4c6c4 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -4276,6 +4276,8 @@ nil | [remove_item(Entity entity, bool autokill_check)](https://github.com/spelu nil | [apply_db()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apply_db) | Applies changes made in `entity.type` [Vec2](#Vec2) | [get_absolute_velocity()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_absolute_velocity) | Get's the velocity relative to the game world, only for movable or liquid entities [AABB](#AABB) | [get_hitbox(optional use_render_pos)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_hitbox) | `use_render_pos` default is `false` +nil | [attach(Entity new_overlay)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=attach) | Attach to other entity (at the current relative position to it) +nil | [detach(optional check_autokill)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=detach) | Detach from overlay [CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. [CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. diff --git a/src/game_api/entities_activefloors.cpp b/src/game_api/entities_activefloors.cpp index ba2abf8ee..b66b62948 100644 --- a/src/game_api/entities_activefloors.cpp +++ b/src/game_api/entities_activefloors.cpp @@ -29,12 +29,7 @@ void Drill::trigger(std::optional play_sound_effect) { return; } - - if (overlay != nullptr) - { - overlay->remove_item(this, true); - } - + detach(true); move_state = 6; flags = flags & ~(1U << (10 - 1)); diff --git a/src/game_api/entity.hpp b/src/game_api/entity.hpp index 0a7c1cad8..1ac46d991 100644 --- a/src/game_api/entity.hpp +++ b/src/game_api/entity.hpp @@ -223,6 +223,25 @@ class Entity { destroy_recursive(std::nullopt, {}, RECURSIVE_MODE::NONE); } + /// Detach from overlay + void detach(std::optional check_autokill) + { + if (overlay) + overlay->remove_item(this, check_autokill.value_or(true)); + } + /// Attach to other entity (at the current relative position to it) + void attach(Entity* new_overlay) + { + if (new_overlay == overlay) + return; + + detach(false); + auto const pos = new_overlay->abs_position(); + x -= pos.x; + y -= pos.y; + overlay = new_overlay; + overlay->items.insert(this, false); + } // for supporting HookableVTable uint32_t get_aux_id() const diff --git a/src/game_api/entity_db.cpp b/src/game_api/entity_db.cpp index 717ee2bec..2237a4ebc 100644 --- a/src/game_api/entity_db.cpp +++ b/src/game_api/entity_db.cpp @@ -78,11 +78,11 @@ ENT_TYPE to_id(std::string_view name) { const EntityFactory* entity_factory_ptr = entity_factory(); if (!entity_factory_ptr) - return -1; + return (ENT_TYPE)~0; map = &entity_factory_ptr->entity_map; } auto it = map->find(std::string(name)); - return it != map->end() ? it->second : -1; + return it != map->end() ? it->second : (ENT_TYPE)~0; } std::string_view to_name(ENT_TYPE id) diff --git a/src/game_api/layer.cpp b/src/game_api/layer.cpp index 7ab172fff..b2d0481d7 100644 --- a/src/game_api/layer.cpp +++ b/src/game_api/layer.cpp @@ -88,10 +88,9 @@ Entity* Layer::spawn_entity_over(ENT_TYPE id, Entity* overlay, float x, float y) Entity* ent = spawn_entity_raw(entity_factory(), id, x, y, is_back_layer, overlay, true); - const auto param_5 = true; - if (((bool*)this)[0x64490] == false && param_5 == false) + if (is_layer_loading == false) { - add_item_ptr(((Entity**)this)[0x64440 / 0x8], ent, false); + unknown_entities4.insert(ent, false); } else { @@ -257,3 +256,10 @@ void Layer::destroy_grid_entity(Entity* ent) ent->destroy(); } } + +void EntityList::insert(Entity* ent, bool b) +{ + using EntityListInsert = void(EntityList*, Entity*, bool); + static EntityListInsert* list_insert = (EntityListInsert*)get_address("entitylist_insert"); + list_insert(this, ent, b); +} diff --git a/src/game_api/layer.hpp b/src/game_api/layer.hpp index 19bc54067..59c4f141e 100644 --- a/src/game_api/layer.hpp +++ b/src/game_api/layer.hpp @@ -83,7 +83,7 @@ struct EntityList using UidRange = Range; using ConstUidRange = Range; - bool empty() + bool empty() const { return size == 0; } @@ -114,6 +114,8 @@ struct EntityList return uids().contains(uid); } + void insert(Entity*, bool); + std::pair operator[](const uint32_t idx) const { return {ent_list[idx], uid_list[idx]}; @@ -155,13 +157,11 @@ struct Layer EntityList unknown_entities2; std::array entities_by_draw_depth; EntityList unknown_entities2a; - EntityList unknown_entities3; // debris, explosions, laserbeams etc. ? + EntityList unknown_entities3; // debris, explosions, laserbeams etc. expired_entities ? EntityList unknown_entities4; // explosions, laserbeams, BG_LEVEL_*_SOOT ? only for short time while there are spawned? std::vector unknown_vector; // add_to_layer uses this std::set* unknown6; // triggered by floor entity destruction? needs more testing - // List of items that were destroyed and are waiting to have the dtor called - // and then be returned to the entity pool - EntityList expired_entities; + EntityList unknown_entities5; bool is_layer_loading; bool unknown14; diff --git a/src/game_api/movable.hpp b/src/game_api/movable.hpp index b507b3b36..84da52ead 100644 --- a/src/game_api/movable.hpp +++ b/src/game_api/movable.hpp @@ -203,14 +203,14 @@ class Movable : public Entity virtual void on_release() = 0; // 81, only for hired hands and lava pots virtual void generate_fall_poof_particles() = 0; // 82, entity.velocityy must be < -0.12 to generate a poof, might do other stuff regarding falling/landing /// Applies gravity to entity. Disable to float like on hoverpack. - virtual void handle_fall_logic(float) = 0; // 83, adjusts entity.velocityy when falling - virtual void apply_friction(float, bool vertical, float) = 0; // 84, applies entity.type.friction to entity.velocityx, the two floats for characters just multiply the friction, could also be returning the value - virtual bool can_break_block(bool horizontal, Entity* block) = 0; // 85, check on collision if the entity should break the block, used for stuff like drill, hundun etc. surprisingly no mattoc - virtual void break_block(bool camera_shake, Entity* block) = 0; // 86 - virtual void v87(Entity* entity, float, Entity* floor, float, bool) = 0; // 87, on_contact_with_ground ? calls on_stood_on_by, on_fall_onto - virtual void v88(Entity* entity, float vecloty) = 0; // 88, on_ragdoll? - for player, triggers only when you throw him into wall/ground/celling - virtual bool v89(void*, void*, bool, bool default_return_flipped) = 0; // 89, triggers on item_rubble?, first parameter only tested if it's 0 for punishball, ignored in the rest, second parameter never used (leftover?) - virtual void on_crushed_by(Entity*) = 0; // 90, e.g. crushed by elevator, punishball, pushblock, crushtrap (not quillback or boulder) - virtual SoundMeta* on_fall_onto(SOUNDID play_sound_id, Entity* fell_on_entity) = 0; // 91, plays the sfx at the entity and sets sound parameters - virtual void on_instakill_death() = 0; // 92, seems to only trigger for enemies that die in one hit, creates some big struct on stack, feeds it to some unknown function + virtual void handle_fall_logic(float) = 0; // 83, adjusts entity.velocityy when falling + virtual void apply_friction(float, bool vertical, float) = 0; // 84, applies entity.type.friction to entity.velocityx, the two floats for characters just multiply the friction, could also be returning the value + virtual bool can_break_block(bool horizontal, Entity* block) = 0; // 85, check on collision if the entity should break the block, used for stuff like drill, hundun etc. surprisingly no mattoc + virtual void break_block(bool camera_shake, Entity* block) = 0; // 86 + virtual void v87(Entity* entity, float, Entity* floor, float, bool) = 0; // 87, on_contact_with_ground ? calls on_stood_on_by, on_fall_onto + virtual void v88(Entity* entity, float vecloty) = 0; // 88, on_ragdoll? - for player, triggers only when you throw him into wall/ground/celling + virtual bool v89(void*, void*, bool, bool default_return_flipped) = 0; // 89, triggers on item_rubble?, first parameter only tested if it's 0 for punishball, ignored in the rest, second parameter never used (leftover?) + virtual void on_crushed_by(Entity*) = 0; // 90, e.g. crushed by elevator, punishball, pushblock, crushtrap (not quillback or boulder) + virtual SoundMeta* on_fall_onto(SOUNDID play_sound_id, Entity* fell_on_entity) = 0; // 91, plays the sfx at the entity and sets sound parameters + virtual void on_instakill_death() = 0; // 92, seems to only trigger for enemies that die in one hit, creates some big struct on stack, feeds it to some unknown function }; diff --git a/src/game_api/rpc.cpp b/src/game_api/rpc.cpp index 6ef647bd9..45afa2ce5 100644 --- a/src/game_api/rpc.cpp +++ b/src/game_api/rpc.cpp @@ -69,6 +69,9 @@ void attach_entity(Entity* overlay, Entity* attachee) { if (attachee->overlay) { + if (attachee->overlay == overlay) + return; + attachee->overlay->remove_item(attachee, false); } @@ -79,9 +82,7 @@ void attach_entity(Entity* overlay, Entity* attachee) attachee->special_offsety = attachee->y; attachee->overlay = overlay; - using AddItemPtr = void(EntityList*, Entity*, bool); - static AddItemPtr* add_item_ptr = (AddItemPtr*)get_address("add_item_ptr"); - add_item_ptr(&overlay->items, attachee, false); + overlay->items.insert(attachee, false); } void attach_entity_by_uid(uint32_t overlay_uid, uint32_t attachee_uid) @@ -144,21 +145,6 @@ void stack_entities(uint32_t bottom_uid, uint32_t top_uid, const float (&offset) } } -void teleport_entity_abs(Entity* ent, float dx, float dy, float vx, float vy) -{ - if (ent->overlay) - ent->overlay->remove_item(ent, false); - - ent->x = dx; - ent->y = dy; - if (ent->is_movable()) - { - auto movable_ent = ent->as(); - movable_ent->velocityx = vx; - movable_ent->velocityy = vy; - } -} - void move_entity_abs(uint32_t uid, float x, float y, float vx, float vy) { auto ent = get_entity_ptr(uid); @@ -170,7 +156,15 @@ void move_entity_abs(uint32_t uid, float x, float y, float vx, float vy) } else { - teleport_entity_abs(ent, x, y, vx, vy); + ent->detach(false); + ent->x = x; + ent->y = y; + if (ent->is_movable()) + { + auto movable_ent = ent->as(); + movable_ent->velocityx = vx; + movable_ent->velocityy = vy; + } } } } @@ -188,7 +182,15 @@ void move_entity_abs(uint32_t uid, float x, float y, float vx, float vy, LAYER l } else { - teleport_entity_abs(ent, offset.x + x, offset.y + y, vx, vy); + ent->detach(false); + ent->x = offset.x + x; + ent->y = offset.y + y; + if (ent->is_movable()) + { + auto movable_ent = ent->as(); + movable_ent->velocityx = vx; + movable_ent->velocityy = vy; + } ent->set_layer(layer); } } @@ -1234,8 +1236,7 @@ void move_grid_entity(int32_t uid, float x, float y, LAYER layer) const auto actual_layer = enum_to_layer(layer, offset); state.layer(entity->layer)->move_grid_entity(entity, offset.x + x, offset.y + y, state.layer(actual_layer)); - if (entity->overlay) - entity->overlay->remove_item(entity, false); + entity->detach(false); entity->x = offset.x + x; entity->y = offset.y + y; entity->set_layer(layer); diff --git a/src/game_api/script/usertypes/entity_lua.cpp b/src/game_api/script/usertypes/entity_lua.cpp index 5ee943879..25314e846 100644 --- a/src/game_api/script/usertypes/entity_lua.cpp +++ b/src/game_api/script/usertypes/entity_lua.cpp @@ -275,6 +275,8 @@ void register_usertypes(sol::state& lua) entity_type["apply_db"] = &Entity::apply_db; entity_type["get_absolute_velocity"] = &Entity::get_absolute_velocity; entity_type["get_hitbox"] = &Entity::get_hitbox; + entity_type["attach"] = &Entity::attach; + entity_type["detach"] = &Entity::detach; /* Entity // user_data diff --git a/src/game_api/search.cpp b/src/game_api/search.cpp index d83b5cd38..c41c1add3 100644 --- a/src/game_api/search.cpp +++ b/src/game_api/search.cpp @@ -655,8 +655,8 @@ std::unordered_map g_address_rules{ .function_start(), }, { - "add_item_ptr"sv, - // Used in spawn_entity as `add_item_ptr(overlay + 0x18, spawned_entity, false)` + "entitylist_insert"sv, + // Used in spawn_entity as `entitylist_insert(overlay + 0x18, spawned_entity, false)` PatternCommandBuffer{} .find_inst("\xe8****\x44\x88\x76"sv) .decode_call() diff --git a/src/injected/ui.cpp b/src/injected/ui.cpp index b7d578e2f..58ad5c6f1 100644 --- a/src/injected/ui.cpp +++ b/src/injected/ui.cpp @@ -1874,8 +1874,7 @@ void toggle_noclip() auto player = (Movable*)ent->topmost_mount(); if (options["noclip"]) { - if (player->overlay) - player->overlay->remove_item(player, false); + player->detach(false); player->type->max_speed = 0.3f; } else @@ -7516,18 +7515,7 @@ void render_entity_props(int uid, bool detached = false) ImGui::SameLine(); if (ImGui::Button("Void##VoidEntity")) { - if (entity->overlay) - { - auto mount = entity->overlay->as(); // pre casting to movable before checking - if (entity->overlay->is_movable() && mount->holding_uid == entity->uid) - { - mount->drop(); - } - else - { - mount->remove_item(entity, false); - } - } + entity->detach(true); entity->overlay = nullptr; entity->y -= 1000.0; } @@ -7553,7 +7541,7 @@ void render_entity_props(int uid, bool detached = false) if (submenu("State")) { auto overlay = entity->overlay; - if (overlay && !IsBadReadPtr(overlay, 0x178)) + if (overlay) { if (overlay->type->search_flags & 0x2) // MOUNT { @@ -7563,7 +7551,8 @@ void render_entity_props(int uid, bool detached = false) { overlay->as()->remove_rider(); } - render_uid(overlay->uid, "StateRiding"); + else + render_uid(overlay->uid, "StateRiding"); } else { @@ -7572,19 +7561,12 @@ void render_entity_props(int uid, bool detached = false) if (ImGui::Button("Detach")) { if (entity->type->search_flags & 0x1) // PLAYER - { entity->as()->let_go(); - } - else if (overlay->is_movable() && overlay->as()->holding_uid == entity->uid) - { - overlay->as()->drop(); - } else - { - overlay->remove_item(entity, true); - } + entity->detach(true); } - render_uid(overlay->uid, "StateAttached"); + else + render_uid(overlay->uid, "StateAttached"); } } else diff --git a/src/injected/ui_util.cpp b/src/injected/ui_util.cpp index c4ea81d68..aee48aa72 100644 --- a/src/injected/ui_util.cpp +++ b/src/injected/ui_util.cpp @@ -94,10 +94,9 @@ float UI::get_zoom_level() } void teleport_entity(Entity* ent, float dx, float dy, bool s, float vx, float vy, bool snap) { - if (ent->overlay) - ent->overlay->remove_item(ent, false); + ent->detach(false); - auto topmost = ent->topmost_mount(); // we just detached from overlay, so this is kind of pointelss + auto topmost = ent->topmost_mount(); // we just detached from overlay, so this is kind of pointless if (!s) { auto [x_pos, y_pos] = topmost->abs_position(); @@ -138,8 +137,7 @@ void teleport_entity(Entity* ent, float dx, float dy, bool s, float vx, float vy } void UI::teleport_entity_abs(Entity* ent, float dx, float dy, float vx, float vy) { - if (ent->overlay) - ent->overlay->remove_item(ent, false); + ent->detach(false); ent->x = dx; ent->y = dy; From 5a09f690001200a921c57d6e2d0789d9a652744b Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sun, 6 Oct 2024 16:26:53 +0200 Subject: [PATCH 11/21] fix invalidating iterator in `remove_spawn` --- src/game_api/state.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/game_api/state.cpp b/src/game_api/state.cpp index c6f57dcef..992ccab3a 100644 --- a/src/game_api/state.cpp +++ b/src/game_api/state.cpp @@ -1063,11 +1063,12 @@ Logic* LogicList::start_logic(LOGIC idx) void LogicList::stop_logic(LOGIC idx) { - if ((uint32_t)idx > 27 || logic_indexed[(uint32_t)idx] == nullptr) + auto index = static_cast(idx); + if (index > 27 || logic_indexed[index] == nullptr) return; - delete logic_indexed[(uint32_t)idx]; - logic_indexed[(uint32_t)idx] = nullptr; + delete logic_indexed[index]; + logic_indexed[index] = nullptr; } void LogicList::stop_logic(Logic* log) @@ -1075,20 +1076,15 @@ void LogicList::stop_logic(Logic* log) if (log == nullptr) return; - auto idx = log->logic_index; + auto idx = static_cast(log->logic_index); delete log; - logic_indexed[(uint32_t)idx] = nullptr; + logic_indexed[idx] = nullptr; } void LogicMagmamanSpawn::remove_spawn(uint32_t x, uint32_t y) { - for (auto it = magmaman_positions.begin(); it < magmaman_positions.end(); ++it) - { - if (it->x == x && it->y == y) - { - magmaman_positions.erase(it); - } - } + std::erase_if(magmaman_positions, [x, y](MagmamanSpawnPosition& m_pos) + { return (m_pos.x == x && m_pos.y == y); }); } void update_camera_position() From 665428d285dc1adc78bf5e89a4f4df9ec3fc3cfb Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:23:11 +0100 Subject: [PATCH 12/21] fix Backpack subclass in lua, add more hookable functions to lua, test them etc. some comments and name changes, filter out bad pointers in vtable_sizes generated by info_dump --- docs/game_data/lua_enums.txt | 12 +- docs/game_data/spel2.lua | 86 +++++++++----- docs/game_data/vtable_sizes.csv | 8 +- docs/src/includes/_enums.md | 14 ++- docs/src/includes/_types.md | 92 ++++++++++----- src/game_api/entities_chars.hpp | 7 +- src/game_api/entities_items.hpp | 6 +- src/game_api/entities_monsters.hpp | 2 +- src/game_api/entities_mounts.hpp | 3 +- src/game_api/entity.hpp | 34 +++--- src/game_api/entity_db.hpp | 4 +- src/game_api/layer.cpp | 2 - src/game_api/movable.hpp | 21 ++-- .../script/usertypes/entities_items_lua.cpp | 12 +- src/game_api/script/usertypes/entity_lua.cpp | 1 + src/game_api/script/usertypes/vtables_lua.cpp | 106 +++++++++++++++++- src/game_api/sound_manager.hpp | 2 +- src/info_dump/main.cpp | 7 +- 18 files changed, 300 insertions(+), 119 deletions(-) diff --git a/docs/game_data/lua_enums.txt b/docs/game_data/lua_enums.txt index ca863618f..b0ede4f95 100644 --- a/docs/game_data/lua_enums.txt +++ b/docs/game_data/lua_enums.txt @@ -329,12 +329,16 @@ DYNAMIC_TEXTURE = { KALI_STATUE = -9 } ENTITY_OVERRIDE = { + ACCELERATION = 100, + ACQUIRE = 93, ACTIVATE = 25, APPLY_FRICTION = 84, APPLY_METADATA = 28, APPLY_MOVEMENT = 71, APPLY_VELOCITY = 42, ATTACK = 46, + BLOOD_COLLISION = 93, + BODY_DESTRUCTION = 92, BREAK_BLOCK = 86, CALCULATE_JUMP_VELOCITY = 40, CAN_BE_PICKED_UP_BY = 68, @@ -358,9 +362,8 @@ ENTITY_OVERRIDE = { FLOOR_UPDATE = 38, FREEZE = 52, FRICTION = 19, + GENERATE_DAMAGE_PARTICLES = 8, GENERATE_FALL_POOF_PARTICLES = 82, - GENERATE_STOMP_DAMAGE_PARTICLES = 8, - GET_COLLISION_INFO = 38, GET_DAMAGE = 43, GET_DAMAGE_SOUND = 50, GET_HELD_ENTITY = 22, @@ -368,7 +371,6 @@ ENTITY_OVERRIDE = { HIDE_HUD = 41, INIT = 36, INITIALIZE = 75, - INSTAKILL_DEATH = 92, IS_IN_LIQUID = 12, IS_ON_FIRE = 45, IS_POWERUP_CAPABLE = 74, @@ -385,6 +387,8 @@ ENTITY_OVERRIDE = { PICKED_UP_BY = 68, PICK_UP = 67, PROCESS_INPUT = 78, + PUTTING_OFF = 97, + PUTTING_ON = 96, RELEASE = 81, REMOVE_ITEM = 21, RESET_DRAW_DEPTH = 18, @@ -393,6 +397,7 @@ ENTITY_OVERRIDE = { SET_DRAW_DEPTH = 17, SET_INVISIBLE = 15, SET_STANDING_ON = 59, + SPAWN_PROJECTILE = 93, SPRINT_FACTOR = 39, STANDING_ON = 60, STOMPED_BY = 61, @@ -402,6 +407,7 @@ ENTITY_OVERRIDE = { THROWN_BY = 62, THROWN_INTO = 47, TRIGGER_ACTION = 24, + TRIGGER_EXPLOSION = 94, UPDATE_STATE_MACHINE = 2, WALKED_OFF = 30, WALKED_ON = 29, diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index 9d4a0de26..d0d0a99ad 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -2470,8 +2470,8 @@ function PRNG:random(min, max) end ---@field blood_content integer ---@field leaves_corpse_behind boolean ---@field description STRINGID - ---@field sound_killed_by_player integer - ---@field sound_killed_by_other integer + ---@field sound_killed_by_player SOUNDID + ---@field sound_killed_by_other SOUNDID ---@field animations table ---@field default_special_offsetx number ---@field default_special_offsetx number @@ -2536,7 +2536,8 @@ function PRNG:random(min, max) end ---@field set_texture fun(self, texture_id: TEXTURE): boolean @Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one ---@field set_draw_depth fun(self, draw_depth: integer, b3f: integer): nil ---@field reset_draw_depth fun(self): nil - ---@field liberate_from_shop fun(self, clear_parrent: boolean): nil @`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 + ---@field friction fun(self): number @Friction of this entity, affects it's contact with other entities (how fast it slows down on the floor, how fast it can move but also the other way around for floors/activefloors: how other entities can move on it) + ---@field liberate_from_shop fun(self, clear_parrent: boolean): nil @`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought ---@field get_held_entity fun(self): Entity ---@field set_layer fun(self, layer: LAYER): nil @Moves the entity to specified layer with all it's items, nothing else happens, so this does not emulate a door transition ---@field apply_layer fun(self): nil @Adds the entity to its own layer, to add it to entity lookup tables without waiting for a state update @@ -2557,11 +2558,11 @@ function PRNG:random(min, max) end ---@field can_be_pushed fun(self): boolean ---@field update fun(self): nil ---@field flip fun(self, left: boolean): nil - ---@field remove_item fun(self, entity: Entity, autokill_check: boolean): nil + ---@field remove_item fun(self, entity: Entity, autokill_check: boolean): nil @Can be called multiple times for the same entity (for example when play throws/drops entity from it's hands) ---@field apply_db fun(self): nil @Applies changes made in `entity.type` ---@field get_absolute_velocity fun(self): Vec2 @Get's the velocity relative to the game world, only for movable or liquid entities ---@field get_hitbox fun(self, use_render_pos: boolean?): AABB @`use_render_pos` default is `false` - ---@field attach fun(self, new_overlay: Entity): nil @Attach to other entity (at the current relative postion to it) + ---@field attach fun(self, new_overlay: Entity): nil @Attach to other entity (at the current relative position to it) ---@field detach fun(self, check_autokill: boolean?): nil @Detach from overlay ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. @@ -2578,8 +2579,8 @@ function PRNG:random(min, max) end ---@field set_post_on_collision1 fun(self, fun: fun(self: Entity, other_entity: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil on_collision1(Entity self, Entity other_entity)`
Virtual function docs:
Collisions with stuff that blocks you, like walls, floors, etc. Triggers for entities in it's EntityDB.collision_mask ---@field set_pre_destroy fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool destroy(Entity self)`
Virtual function docs:
Completely removes the entity from existence ---@field set_post_destroy fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil destroy(Entity self)`
Virtual function docs:
Completely removes the entity from existence - ---@field set_pre_generate_stomp_damage_particles fun(self, fun: fun(self: Entity, victim: Entity, damage: DAMAGE_TYPE, boolean: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool generate_stomp_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, boolean)` - ---@field set_post_generate_stomp_damage_particles fun(self, fun: fun(self: Entity, victim: Entity, damage: DAMAGE_TYPE, boolean: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil generate_stomp_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, boolean)` + ---@field set_pre_generate_damage_particles fun(self, fun: fun(self: Entity, victim: Entity, damage: DAMAGE_TYPE, killing: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool generate_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, boolean killing)` + ---@field set_post_generate_damage_particles fun(self, fun: fun(self: Entity, victim: Entity, damage: DAMAGE_TYPE, killing: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil generate_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, boolean killing)` ---@field set_pre_can_be_pushed fun(self, fun: fun(self: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional can_be_pushed(Entity self)` ---@field set_post_can_be_pushed fun(self, fun: fun(self: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil can_be_pushed(Entity self)` ---@field set_pre_is_in_liquid fun(self, fun: fun(self: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional is_in_liquid(Entity self)`
Virtual function docs:
Returns true if entity is in water/lava @@ -2592,12 +2593,12 @@ function PRNG:random(min, max) end ---@field set_post_set_draw_depth fun(self, fun: fun(self: Entity, draw_depth: integer, b3f: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil set_draw_depth(Entity self, integer draw_depth, integer b3f)` ---@field set_pre_reset_draw_depth fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool reset_draw_depth(Entity self)` ---@field set_post_reset_draw_depth fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil reset_draw_depth(Entity self)` - ---@field set_pre_friction fun(self, fun: fun(self: Entity): number?): CallbackId @Hooks before the virtual function.
The callback signature is `optional friction(Entity self)` - ---@field set_post_friction fun(self, fun: fun(self: Entity): number?): CallbackId @Hooks after the virtual function.
The callback signature is `nil friction(Entity self)` + ---@field set_pre_friction fun(self, fun: fun(self: Entity): number?): CallbackId @Hooks before the virtual function.
The callback signature is `optional friction(Entity self)`
Virtual function docs:
Friction of this entity, affects it's contact with other entities (how fast it slows down on the floor, how fast it can move but also the other way around for floors/activefloors: how other entities can move on it) + ---@field set_post_friction fun(self, fun: fun(self: Entity): number?): CallbackId @Hooks after the virtual function.
The callback signature is `nil friction(Entity self)`
Virtual function docs:
Friction of this entity, affects it's contact with other entities (how fast it slows down on the floor, how fast it can move but also the other way around for floors/activefloors: how other entities can move on it) ---@field set_pre_set_as_sound_source fun(self, fun: fun(self: Entity, soundmeta: SoundMeta): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool set_as_sound_source(Entity self, SoundMeta soundmeta)` ---@field set_post_set_as_sound_source fun(self, fun: fun(self: Entity, soundmeta: SoundMeta): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil set_as_sound_source(Entity self, SoundMeta soundmeta)` - ---@field set_pre_remove_item fun(self, fun: fun(self: Entity, entity: Entity, autokill_check: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool remove_item(Entity self, Entity entity, boolean autokill_check)` - ---@field set_post_remove_item fun(self, fun: fun(self: Entity, entity: Entity, autokill_check: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil remove_item(Entity self, Entity entity, boolean autokill_check)` + ---@field set_pre_remove_item fun(self, fun: fun(self: Entity, entity: Entity, autokill_check: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool remove_item(Entity self, Entity entity, boolean autokill_check)`
Virtual function docs:
Can be called multiple times for the same entity (for example when play throws/drops entity from it's hands) + ---@field set_post_remove_item fun(self, fun: fun(self: Entity, entity: Entity, autokill_check: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil remove_item(Entity self, Entity entity, boolean autokill_check)`
Virtual function docs:
Can be called multiple times for the same entity (for example when play throws/drops entity from it's hands) ---@field set_pre_get_held_entity fun(self, fun: fun(self: Entity): Entity?): CallbackId @Hooks before the virtual function.
The callback signature is `optional get_held_entity(Entity self)` ---@field set_post_get_held_entity fun(self, fun: fun(self: Entity): Entity?): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_held_entity(Entity self)` ---@field set_pre_trigger_action fun(self, fun: fun(self: Entity, user: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleporter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) @@ -2618,8 +2619,8 @@ function PRNG:random(min, max) end ---@field set_post_ledge_grab fun(self, fun: fun(self: Entity, who: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil ledge_grab(Entity self, Entity who)` ---@field set_pre_stood_on fun(self, fun: fun(self: Entity, Vec2: Entity entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool stood_on(Entity self, Entity entity Vec2)` ---@field set_post_stood_on fun(self, fun: fun(self: Entity, Vec2: Entity entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil stood_on(Entity self, Entity entity Vec2)` - ---@field set_pre_liberate_from_shop fun(self, fun: fun(self: Entity, clear_parrent: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool liberate_from_shop(Entity self, boolean clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 - ---@field set_post_liberate_from_shop fun(self, fun: fun(self: Entity, clear_parrent: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil liberate_from_shop(Entity self, boolean clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 + ---@field set_pre_liberate_from_shop fun(self, fun: fun(self: Entity, clear_parrent: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool liberate_from_shop(Entity self, boolean clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought + ---@field set_post_liberate_from_shop fun(self, fun: fun(self: Entity, clear_parrent: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil liberate_from_shop(Entity self, boolean clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought ---@field set_pre_init fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool init(Entity self)` ---@field set_post_init fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil init(Entity self)` local Entity = nil @@ -2722,11 +2723,11 @@ function Entity:destroy_recursive() end ---@field set_position fun(self, to_x: number, to_y: number): nil @Set the absolute position of an entity and offset all rendering related things accordingly to teleport without any interpolation or graphical glitches. If the camera is focused on the entity, it is also moved. ---@field process_input fun(self): nil ---@field calculate_jump_velocity fun(self, dont_ignore_liquid: boolean): number - ---@field apply_velocity fun(self, velocities: Vec2, ignore_weight: boolean): nil + ---@field apply_velocity fun(self, velocities: Vec2, ignore_weight: boolean): nil @Mostly used for ragdoll by the game ---@field get_damage fun(self): integer @Returns the damage that the entity deals ---@field attack fun(self, victim: Entity): boolean @Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) ---@field thrown_into fun(self, victim: Entity): boolean @Same as above, but for being thrown into something and potentially dealing damage that way - ---@field get_damage_sound fun(self, damage: DAMAGE_TYPE): integer @returns sound id for the damage taken, return 0 to make it silence + ---@field get_damage_sound fun(self, damage: DAMAGE_TYPE): SOUNDID @returns sound id for the damage taken, return 0 to make it silence ---@field copy_extra_info fun(self, clone: Entity, some_entity_uid: integer): nil @Entities must be of the same type! ---@field cutscene CutsceneBehavior ---@field clear_cutscene fun(self): nil @@ -2739,16 +2740,12 @@ function Entity:destroy_recursive() end ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. ---@field set_pre_can_jump fun(self, fun: fun(self: Movable): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional can_jump(Movable self)`
Virtual function docs:
Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. ---@field set_post_can_jump fun(self, fun: fun(self: Movable): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil can_jump(Movable self)`
Virtual function docs:
Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. - ---@field set_pre_get_collision_info fun(self, fun: fun(self: Movable, dest: CollisionInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool get_collision_info(Movable self, CollisionInfo dest)` - ---@field set_post_get_collision_info fun(self, fun: fun(self: Movable, dest: CollisionInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_collision_info(Movable self, CollisionInfo dest)` ---@field set_pre_sprint_factor fun(self, fun: fun(self: Movable): number?): CallbackId @Hooks before the virtual function.
The callback signature is `optional sprint_factor(Movable self)` ---@field set_post_sprint_factor fun(self, fun: fun(self: Movable): number?): CallbackId @Hooks after the virtual function.
The callback signature is `nil sprint_factor(Movable self)` ---@field set_pre_calculate_jump_velocity fun(self, fun: fun(self: Movable, dont_ignore_liquid: boolean): number?): CallbackId @Hooks before the virtual function.
The callback signature is `optional calculate_jump_velocity(Movable self, boolean dont_ignore_liquid)` ---@field set_post_calculate_jump_velocity fun(self, fun: fun(self: Movable, dont_ignore_liquid: boolean): number?): CallbackId @Hooks after the virtual function.
The callback signature is `nil calculate_jump_velocity(Movable self, boolean dont_ignore_liquid)` - ---@field set_pre_get_animation_map fun(self, fun: fun(self: Movable): table): CallbackId @Hooks before the virtual function.
The callback signature is `optional> get_animation_map(Movable self)` - ---@field set_post_get_animation_map fun(self, fun: fun(self: Movable): table): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_animation_map(Movable self)` - ---@field set_pre_apply_velocity fun(self, fun: fun(self: Movable, velocities: Vec2, ignore_weight: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool apply_velocity(Movable self, Vec2 velocities, boolean ignore_weight)` - ---@field set_post_apply_velocity fun(self, fun: fun(self: Movable, velocities: Vec2, ignore_weight: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil apply_velocity(Movable self, Vec2 velocities, boolean ignore_weight)` + ---@field set_pre_apply_velocity fun(self, fun: fun(self: Movable, velocities: Vec2, ignore_weight: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool apply_velocity(Movable self, Vec2 velocities, boolean ignore_weight)`
Virtual function docs:
Mostly used for ragdoll by the game + ---@field set_post_apply_velocity fun(self, fun: fun(self: Movable, velocities: Vec2, ignore_weight: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil apply_velocity(Movable self, Vec2 velocities, boolean ignore_weight)`
Virtual function docs:
Mostly used for ragdoll by the game ---@field set_pre_get_damage fun(self, fun: fun(self: Movable): integer?): CallbackId @Hooks before the virtual function.
The callback signature is `optional get_damage(Movable self)`
Virtual function docs:
Returns the damage that the entity deals ---@field set_post_get_damage fun(self, fun: fun(self: Movable): integer?): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_damage(Movable self)`
Virtual function docs:
Returns the damage that the entity deals ---@field set_pre_is_on_fire fun(self, fun: fun(self: Movable): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional is_on_fire(Movable self)` @@ -2761,8 +2758,8 @@ function Entity:destroy_recursive() end ---@field set_post_damage fun(self, fun: fun(self: Movable, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, integer damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, integer unknown_damage_phase, integer stun_amount, integer iframes, boolean unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer ---@field set_pre_on_hit fun(self, fun: fun(self: Movable, damage_dealer: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. ---@field set_post_on_hit fun(self, fun: fun(self: Movable, damage_dealer: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. - ---@field set_pre_get_damage_sound fun(self, fun: fun(self: Movable, damage: DAMAGE_TYPE): integer?): CallbackId @Hooks before the virtual function.
The callback signature is `optional get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence - ---@field set_post_get_damage_sound fun(self, fun: fun(self: Movable, damage: DAMAGE_TYPE): integer?): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence + ---@field set_pre_get_damage_sound fun(self, fun: fun(self: Movable, damage: DAMAGE_TYPE): SOUNDID?): CallbackId @Hooks before the virtual function.
The callback signature is `optional get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence + ---@field set_post_get_damage_sound fun(self, fun: fun(self: Movable, damage: DAMAGE_TYPE): SOUNDID?): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence ---@field set_pre_stun fun(self, fun: fun(self: Movable, framecount: integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool stun(Movable self, integer framecount)` ---@field set_post_stun fun(self, fun: fun(self: Movable, framecount: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil stun(Movable self, integer framecount)` ---@field set_pre_freeze fun(self, fun: fun(self: Movable, framecount: integer, ignore_lava: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool freeze(Movable self, integer framecount, boolean ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time @@ -2817,8 +2814,8 @@ function Entity:destroy_recursive() end ---@field set_post_break_block fun(self, fun: fun(self: Movable, camera_shake: boolean, block: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil break_block(Movable self, boolean camera_shake, Entity block)` ---@field set_pre_crush fun(self, fun: fun(self: Movable, entity: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool crush(Movable self, Entity entity)` ---@field set_post_crush fun(self, fun: fun(self: Movable, entity: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil crush(Movable self, Entity entity)` - ---@field set_pre_instakill_death fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool instakill_death(Movable self)` - ---@field set_post_instakill_death fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil instakill_death(Movable self)` + ---@field set_pre_body_destruction fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool body_destruction(Movable self)` + ---@field set_post_body_destruction fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil body_destruction(Movable self)` local Movable = nil ---Move a movable according to its velocity, can disable gravity ---Will also update `movable.animation_frame` and various timers and counters @@ -2849,6 +2846,11 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field get_powerups fun(self): ENT_TYPE[] @Return all powerups that the entity has ---@field unequip_backitem fun(self): nil @Unequips the currently worn backitem ---@field worn_backitem fun(self): integer @Returns the uid of the currently worn backitem, or -1 if wearing nothing + ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. + ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. + ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. + ---@field set_pre_blood_collision fun(self, fun: fun(self: PowerupCapable): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional blood_collision(PowerupCapable self)` + ---@field set_post_blood_collision fun(self, fun: fun(self: PowerupCapable): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil blood_collision(PowerupCapable self)` ---@class Inventory ---@field money integer @Sum of the money collected in current level @@ -3810,21 +3812,36 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field scale_ver number ---@field is_big_bomb boolean @is bomb from powerpack ----@class Backpack : Movable +---@class Backpack : Powerup ---@field explosion_trigger boolean @More like on fire trigger, the explosion happens when the timer reaches > 29 ---@field explosion_timer integer ---@field trigger_explosion fun(self): nil + ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. + ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. + ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. + ---@field set_pre_trigger_explosion fun(self, fun: fun(self: Backpack): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool trigger_explosion(Backpack self)` + ---@field set_post_trigger_explosion fun(self, fun: fun(self: Backpack): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil trigger_explosion(Backpack self)` ---@class Projectile : Movable ---@class Purchasable : Movable ---@field acquire fun(self, who: Entity): nil @Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money + ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. + ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. + ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. + ---@field set_pre_acquire fun(self, fun: fun(self: Purchasable, who: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool acquire(Purchasable self, Entity who)`
Virtual function docs:
Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money + ---@field set_post_acquire fun(self, fun: fun(self: Purchasable, who: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil acquire(Purchasable self, Entity who)`
Virtual function docs:
Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money ---@class DummyPurchasableEntity : Purchasable ---@field replace_entity Entity ---@field exploding boolean ---@field explosion_timer integer @Explodes when timer reaches 30 ---@field trigger_explosion fun(self, who: Entity): nil @Transfers ownership etc. for who to blame, sets the exploding bool + ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. + ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. + ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. + ---@field set_pre_trigger_explosion fun(self, fun: fun(self: DummyPurchasableEntity, who: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool trigger_explosion(DummyPurchasableEntity self, Entity who)`
Virtual function docs:
Transfers ownership etc. for who to blame, sets the exploding bool + ---@field set_post_trigger_explosion fun(self, fun: fun(self: DummyPurchasableEntity, who: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil trigger_explosion(DummyPurchasableEntity self, Entity who)`
Virtual function docs:
Transfers ownership etc. for who to blame, sets the exploding bool ---@class Bow : Purchasable ---@field get_arrow_special_offset fun(self): number @When lying on the ground @@ -3836,6 +3853,11 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field flame_on boolean ---@field fuel integer ---@field acceleration fun(self): number + ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. + ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. + ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. + ---@field set_pre_acceleration fun(self, fun: fun(self: Jetpack): number?): CallbackId @Hooks before the virtual function.
The callback signature is `optional acceleration(Jetpack self)` + ---@field set_post_acceleration fun(self, fun: fun(self: Jetpack): number?): CallbackId @Hooks after the virtual function.
The callback signature is `nil acceleration(Jetpack self)` ---@class TeleporterBackpack : Backpack ---@field teleport_number integer @@ -4048,6 +4070,11 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field timer integer ---@field bombs_left integer ---@field spawn_projectile fun(self): nil + ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. + ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. + ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. + ---@field set_pre_spawn_projectile fun(self, fun: fun(self: OlmecCannon): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool spawn_projectile(OlmecCannon self)` + ---@field set_post_spawn_projectile fun(self, fun: fun(self: OlmecCannon): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil spawn_projectile(OlmecCannon self)` ---@class Landmine : LightEmitter ---@field timer integer @explodes at 57, if you set it to 58 will count to overflow @@ -4177,6 +4204,13 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field ropes integer ---@class Powerup : Movable + ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. + ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. + ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. + ---@field set_pre_putting_on fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool putting_on(Powerup self, PowerupCapable who)` + ---@field set_post_putting_on fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil putting_on(Powerup self, PowerupCapable who)` + ---@field set_pre_putting_off fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool putting_off(Powerup self, PowerupCapable who)` + ---@field set_post_putting_off fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil putting_off(Powerup self, PowerupCapable who)` ---@class KapalaPowerup : Powerup ---@field amount_of_blood integer diff --git a/docs/game_data/vtable_sizes.csv b/docs/game_data/vtable_sizes.csv index 6c4006715..c7394df04 100644 --- a/docs/game_data/vtable_sizes.csv +++ b/docs/game_data/vtable_sizes.csv @@ -1,10 +1,10 @@ -TypeID,Name,vtable offset,~Entity,create_rendering_info,update_state_machine,kill,on_collision1,destroy,apply_texture,format_shopitem_name,generate_stomp_damage_particles,get_type_field_a8,can_be_pushed,v11,is_in_liquid,check_type_properties_flags_19,get_type_field_60,set_invisible,flip,set_draw_depth,reset_draw_depth,friction,set_as_sound_source,remove_item,get_held_entity,v23,trigger_action,activate,on_collision2,get_metadata,apply_metadata,on_walked_on_by,on_walked_off_by,on_ledge_grab,on_stood_on_by,toggle_backlayer_illumination,v34,liberate_from_shop,apply_db,END OF ENTITY,can_jump,get_collision_info,sprint_factor,calculate_jump_velocity,get_animation_map,apply_velocity,get_damage,get_stomp_damage,is_on_fire,attack,thrown_into,damage,on_hit,get_damage_sound,stun,freeze,light_on_fire,set_cursed,on_spiderweb_collision,set_last_owner_uid_b127,get_last_owner_uid,check_out_of_bounds,set_standing_on,standing_on,on_stomped_on_by,on_thrown_by,copy_extra_info,get_type_id,doesnt_have_spikeshoes,is_player_mount_or_monster,pick_up,can_be_picked_up_by,drop,collect_treasure,apply_movement,damage_entity,v73,is_powerup_capable,initialize,check_is_falling,v77,process_input,post_collision_damage_related,on_picked_up,on_release,generate_fall_poof_particles,handle_fall_logic,apply_friction,can_break_block,break_block,v87,v88,v89,on_crushed_by,on_fall_onto,on_instakill_death,END OF MOVABLE,v93,v94,v95,v96,v97,v98,v99,v100,v101,v102,v103,v104,v105,v106,v107,v108,v109, +TypeID,Name,vtable offset,~Entity,create_rendering_info,update_state_machine,kill,on_collision1,destroy,apply_texture,format_shopitem_name,generate_damage_particles,get_type_field_a8,can_be_pushed,v11,is_in_liquid,check_type_properties_flags_19,get_type_field_60,set_invisible,flip,set_draw_depth,reset_draw_depth,friction,set_as_sound_source,remove_item,get_held_entity,v23,trigger_action,activate,on_collision2,get_metadata,apply_metadata,on_walked_on_by,on_walked_off_by,on_ledge_grab,on_stood_on_by,toggle_backlayer_illumination,v34,liberate_from_shop,apply_db,END OF ENTITY,can_jump,get_collision_info,sprint_factor,calculate_jump_velocity,get_animation_map,apply_velocity,get_damage,get_stomp_damage,is_on_fire,attack,thrown_into,damage,on_hit,get_damage_sound,stun,freeze,light_on_fire,set_cursed,on_spiderweb_collision,set_last_owner_uid_b127,get_last_owner_uid,check_out_of_bounds,set_standing_on,standing_on,on_stomped_on_by,on_thrown_by,copy_extra_info,get_type_id,doesnt_have_spikeshoes,is_player_mount_or_monster,pick_up,can_be_picked_up_by,drop,collect_treasure,apply_movement,damage_entity,v73,is_powerup_capable,initialize,check_is_falling,v77,process_input,post_collision_damage_related,on_picked_up,on_release,generate_fall_poof_particles,handle_fall_logic,apply_friction,can_break_block,break_block,v87,v88,v89,on_crushed_by,on_fall_onto,on_body_destruction,END OF MOVABLE,v93,v94,v95,v96,v97,v98,v99,v100,v101,v102,v103,v104,v105,v106,v107,v108,v109, 1,ENT_TYPE_FLOOR_BORDERTILE,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 2,ENT_TYPE_FLOOR_BORDERTILE_METAL,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 3,ENT_TYPE_FLOOR_BORDERTILE_OCTOPUS,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 4,ENT_TYPE_FLOOR_GENERIC,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 5,ENT_TYPE_FLOOR_SURFACE,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 -6,ENT_TYPE_FLOOR_SURFACE_HIDDEN,48206,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,ret,0x2287cbd0,0x2287d100,ret 0,ret true,ret,ret,ret,ret,0x228bff80,0x2287d100,ret 0,0x228bfe80,ret,ret,0x228bfe90,0x2292e2c0,0x228bdfb0,ret true,ret 0,ret 0,ret,ret,0x228ee610,0x22997220,0x228bdfb0,0x228c4340,ret 0,ret 0,0x22999730,0x22999750,0x22999aa0,0x228c6ab0,0x22999f90,ret true,ret 0,ret 0,0x22999fc0,ret,0x2299a010,0x228c6ab0,0x228bdfb0,0x2289e280,0x2299bf40,0x2299d580,0x2299d8a0,0x229a3840,0x229a3b00,0xffff817e81650173,0xffff817f81650000,0x228a9670 +6,ENT_TYPE_FLOOR_SURFACE_HIDDEN,48206,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,ret,0x2287cbd0,0x2287d100,ret 0,ret true,ret,ret,ret,ret,0x228bff80,0x2287d100,ret 0,0x228bfe80,ret,ret,0x228bfe90,0x2292e2c0,0x228bdfb0,ret true,ret 0,ret 0,ret,ret,0x228ee610,0x22997220,0x228bdfb0,0x228c4340,ret 0,ret 0,0x22999730,0x22999750,0x22999aa0,0x228c6ab0,0x22999f90,ret true,ret 0,ret 0,0x22999fc0,ret,0x2299a010,0x228c6ab0,0x228bdfb0,0x2289e280,0x2299bf40,0x2299d580,0x2299d8a0,0x229a3840,0x229a3b00 7,ENT_TYPE_FLOOR_BASECAMP_SINGLEBED,10626,0x2287aed0,0x227fcd90,ret,0x2297d3f0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x2297d600,0x2297d680,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 8,ENT_TYPE_FLOOR_BASECAMP_DININGTABLE,10626,0x2287aed0,0x227fcd90,ret,0x2297d3f0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x2297d600,0x2297d680,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 9,ENT_TYPE_FLOOR_BASECAMP_LONGTABLE,10626,0x2287aed0,0x227fcd90,ret,0x2297d3f0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x2297d600,0x2297d680,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 @@ -91,7 +91,7 @@ TypeID,Name,vtable offset,~Entity,create_rendering_info,update_state_machine,kil 90,ENT_TYPE_FLOOR_FORCEFIELD_TOP,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 91,ENT_TYPE_FLOOR_HORIZONTAL_FORCEFIELD,8946,0x2287aed0,0x227fcd90,0x22974270,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x22974960,0x227fd790,0x227fd930,0x227fd950,0x22974760,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22974240,END OF ENTITY,0x22928d00,ret,0x2287cbd0 92,ENT_TYPE_FLOOR_HORIZONTAL_FORCEFIELD_TOP,8786,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 -93,ENT_TYPE_FLOOR_PEN,48142,0x2287aed0,0x227fcd90,ret,0x22978910,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x22978990,0x9098015866b000c,0x680118468030c,0x68011816f0009,0x78011816f0009,0x98013816d0008,0x98013816f000a,0xa80138170000b,0xbf7f80098170000b,0xffff8009c0e50000 +93,ENT_TYPE_FLOOR_PEN,48142,0x2287aed0,0x227fcd90,ret,0x22978910,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x22978990 94,ENT_TYPE_FLOOR_TOMB,8906,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x2298cc30,END OF ENTITY,0x22928d00,0x2292c410,0x2288b9e0 95,ENT_TYPE_FLOOR_YAMA_PLATFORM,8866,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x2288d9c0,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2287cbd0 96,ENT_TYPE_FLOOR_EMPRESS_GRAVE,8826,0x2287aed0,0x227fcd90,ret,0x22926290,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x22927b90,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,0x22927f40,ret,ret,0x22928420,ret,ret,0x227fe2f0,0x22928bd0,END OF ENTITY,0x22928d00,0x2292c410,0x2288b9e0 @@ -811,7 +811,7 @@ TypeID,Name,vtable offset,~Entity,create_rendering_info,update_state_machine,kil 841,ENT_TYPE_BG_EGGSAC_STAINS,2460,0x2287aed0,0x227fcd90,ret,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,ret,END OF ENTITY 844,ENT_TYPE_LOGICAL_CONSTELLATION,2840,0x2287aed0,0x227fcd90,ret,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,0x229f53f0,END OF ENTITY 845,ENT_TYPE_LOGICAL_SHOOTING_STARS_SPAWNER,2802,0x2287aed0,0x227fcd90,0x22a004c0,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,0x22a004b0,END OF ENTITY -846,ENT_TYPE_LOGICAL_DOOR,48710,0x2287aed0,0x227fcd90,0x229f8090,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,ret,END OF ENTITY,0xffff8009c0e50000,0x403f8009c1650000 +846,ENT_TYPE_LOGICAL_DOOR,48710,0x2287aed0,0x227fcd90,0x229f8090,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,ret,END OF ENTITY 847,ENT_TYPE_LOGICAL_DOOR_AMBIENT_SOUND,2764,0x2287aed0,0x227fcd90,0x229f83c0,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,0x229f8360,END OF ENTITY 848,ENT_TYPE_LOGICAL_BLACKMARKET_DOOR,2726,0x2287aed0,0x227fcd90,0x229f8090,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,ret,ret 0,ret,ret,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,0x229f3af0,END OF ENTITY 849,ENT_TYPE_LOGICAL_ARROW_TRAP_TRIGGER,48672,0x2287aed0,0x227fcd90,0x229f35f0,0x227fcfd0,ret,0x227fd000,0x227fd0b0,0x227fd110,0x227fd150,0x227fd570,0x227fd580,ret 0,0x227fd5a0,0x227fd730,0x227fd740,0x227fd750,0x227fd770,0x227fd790,0x227fd930,0x227fd950,0x227fd960,0x227fe160,ret 0,0x229f3a20,ret 0,ret,0x229f3a40,ret 0,ret,ret,ret,ret,ret,ret,ret,0x227fe2f0,ret,END OF ENTITY diff --git a/docs/src/includes/_enums.md b/docs/src/includes/_enums.md index 67f124930..5161ebe57 100644 --- a/docs/src/includes/_enums.md +++ b/docs/src/includes/_enums.md @@ -232,7 +232,7 @@ Name | Data | Description [KILL](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.KILL) | 3 | [ON_COLLISION1](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ON_COLLISION1) | 4 | [DESTROY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.DESTROY) | 5 | -[GENERATE_STOMP_DAMAGE_PARTICLES](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GENERATE_STOMP_DAMAGE_PARTICLES) | 8 | +[GENERATE_DAMAGE_PARTICLES](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GENERATE_DAMAGE_PARTICLES) | 8 | [CAN_BE_PUSHED](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CAN_BE_PUSHED) | 10 | [IS_IN_LIQUID](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.IS_IN_LIQUID) | 12 | [SET_INVISIBLE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.SET_INVISIBLE) | 15 | @@ -255,10 +255,8 @@ Name | Data | Description [LIBERATE_FROM_SHOP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.LIBERATE_FROM_SHOP) | 35 | [INIT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.INIT) | 36 | [CAN_JUMP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CAN_JUMP) | 37 | -[GET_COLLISION_INFO](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GET_COLLISION_INFO) | 38 | [SPRINT_FACTOR](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.SPRINT_FACTOR) | 39 | [CALCULATE_JUMP_VELOCITY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CALCULATE_JUMP_VELOCITY) | 40 | -[GET_ANIMATION_MAP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GET_ANIMATION_MAP) | 41 | [APPLY_VELOCITY](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.APPLY_VELOCITY) | 42 | [GET_DAMAGE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GET_DAMAGE) | 43 | [IS_ON_FIRE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.IS_ON_FIRE) | 45 | @@ -294,7 +292,7 @@ Name | Data | Description [CAN_BREAK_BLOCK](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CAN_BREAK_BLOCK) | 85 | [BREAK_BLOCK](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.BREAK_BLOCK) | 86 | [CRUSH](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CRUSH) | 90 | -[INSTAKILL_DEATH](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.INSTAKILL_DEATH) | 92 | +[BODY_DESTRUCTION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.BODY_DESTRUCTION) | 92 | [FLOOR_UPDATE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.FLOOR_UPDATE) | 38 | [ENTER_ATTEMPT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ENTER_ATTEMPT) | 40 | [HIDE_HUD](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.HIDE_HUD) | 41 | @@ -302,6 +300,14 @@ Name | Data | Description [LIGHT_LEVEL](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.LIGHT_LEVEL) | 44 | [IS_UNLOCKED](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.IS_UNLOCKED) | 45 | [CAN_ENTER](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CAN_ENTER) | 46 | +[BLOOD_COLLISION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.BLOOD_COLLISION) | 93 | +[PUTTING_ON](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.PUTTING_ON) | 96 | +[PUTTING_OFF](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.PUTTING_OFF) | 97 | +[TRIGGER_EXPLOSION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.TRIGGER_EXPLOSION) | 99 | +[ACCELERATION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ACCELERATION) | 100 | +[ACQUIRE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ACQUIRE) | 93 | +[TRIGGER_EXPLOSION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.TRIGGER_EXPLOSION) | 94 | +[SPAWN_PROJECTILE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.SPAWN_PROJECTILE) | 93 | ## ENT_FLAG diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 21ec4c6c4..0a70e91e8 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -485,8 +485,8 @@ int | [sacrifice_value](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q int | [blood_content](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=blood_content) | bool | [leaves_corpse_behind](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=leaves_corpse_behind) | [STRINGID](#Aliases) | [description](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=description) | -int | [sound_killed_by_player](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound_killed_by_player) | -int | [sound_killed_by_other](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound_killed_by_other) | +[SOUNDID](#Aliases) | [sound_killed_by_player](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound_killed_by_player) | +[SOUNDID](#Aliases) | [sound_killed_by_other](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=sound_killed_by_other) | map<int, [Animation](#Animation)> | [animations](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=animations) | float | [default_special_offsetx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_special_offsetx) | float | [default_special_offsetx](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=default_special_offsetx) | @@ -4247,7 +4247,8 @@ bool | [overlaps_with(Entity other)](https://github.com/spelunky-fyi/overlunky/s bool | [set_texture(TEXTURE texture_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_texture) | Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one nil | [set_draw_depth(int draw_depth, int b3f)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_draw_depth) | nil | [reset_draw_depth()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=reset_draw_depth) | -nil | [liberate_from_shop(bool clear_parrent)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=liberate_from_shop) | `clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 +float | [friction()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=friction) | Friction of this entity, affects it's contact with other entities (how fast it slows down on the floor, how fast it can move but also the other way around for floors/activefloors: how other entities can move on it) +nil | [liberate_from_shop(bool clear_parrent)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=liberate_from_shop) | `clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought [Entity](#Entity) | [get_held_entity()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_held_entity) | nil | [set_layer(LAYER layer)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_layer) | Moves the entity to specified layer with all it's items, nothing else happens, so this does not emulate a door transition nil | [apply_layer()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apply_layer) | Adds the entity to its own layer, to add it to entity lookup tables without waiting for a state update @@ -4272,7 +4273,7 @@ nil | [destroy_recursive(optional mask, array ent_types, RECURSIV nil | [destroy_recursive()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=destroy_recursive) | Short for using [RECURSIVE_MODE](#RECURSIVE_MODE).NONE nil | [update()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=update) | nil | [flip(bool left)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=flip) | -nil | [remove_item(Entity entity, bool autokill_check)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=remove_item) | +nil | [remove_item(Entity entity, bool autokill_check)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=remove_item) | Can be called multiple times for the same entity (for example when play throws/drops entity from it's hands) nil | [apply_db()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apply_db) | Applies changes made in `entity.type` [Vec2](#Vec2) | [get_absolute_velocity()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_absolute_velocity) | Get's the velocity relative to the game world, only for movable or liquid entities [AABB](#AABB) | [get_hitbox(optional use_render_pos)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_hitbox) | `use_render_pos` default is `false` @@ -4293,8 +4294,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_on_collision1(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_on_collision1) | Hooks after the virtual function.
The callback signature is `nil on_collision1(Entity self, Entity other_entity)`
Virtual function docs:
Collisions with stuff that blocks you, like walls, floors, etc. Triggers for entities in it's EntityDB.collision_mask [CallbackId](#Aliases) | [set_pre_destroy(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_destroy) | Hooks before the virtual function.
The callback signature is `bool destroy(Entity self)`
Virtual function docs:
Completely removes the entity from existence [CallbackId](#Aliases) | [set_post_destroy(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_destroy) | Hooks after the virtual function.
The callback signature is `nil destroy(Entity self)`
Virtual function docs:
Completely removes the entity from existence -[CallbackId](#Aliases) | [set_pre_generate_stomp_damage_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_generate_stomp_damage_particles) | Hooks before the virtual function.
The callback signature is `bool generate_stomp_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, bool)` -[CallbackId](#Aliases) | [set_post_generate_stomp_damage_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_generate_stomp_damage_particles) | Hooks after the virtual function.
The callback signature is `nil generate_stomp_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, bool)` +[CallbackId](#Aliases) | [set_pre_generate_damage_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_generate_damage_particles) | Hooks before the virtual function.
The callback signature is `bool generate_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, bool killing)` +[CallbackId](#Aliases) | [set_post_generate_damage_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_generate_damage_particles) | Hooks after the virtual function.
The callback signature is `nil generate_damage_particles(Entity self, Entity victim, DAMAGE_TYPE damage, bool killing)` [CallbackId](#Aliases) | [set_pre_can_be_pushed(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_can_be_pushed) | Hooks before the virtual function.
The callback signature is `optional can_be_pushed(Entity self)` [CallbackId](#Aliases) | [set_post_can_be_pushed(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_can_be_pushed) | Hooks after the virtual function.
The callback signature is `nil can_be_pushed(Entity self)` [CallbackId](#Aliases) | [set_pre_is_in_liquid(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_is_in_liquid) | Hooks before the virtual function.
The callback signature is `optional is_in_liquid(Entity self)`
Virtual function docs:
Returns true if entity is in water/lava @@ -4307,12 +4308,12 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_set_draw_depth(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_set_draw_depth) | Hooks after the virtual function.
The callback signature is `nil set_draw_depth(Entity self, int draw_depth, int b3f)` [CallbackId](#Aliases) | [set_pre_reset_draw_depth(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_reset_draw_depth) | Hooks before the virtual function.
The callback signature is `bool reset_draw_depth(Entity self)` [CallbackId](#Aliases) | [set_post_reset_draw_depth(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_reset_draw_depth) | Hooks after the virtual function.
The callback signature is `nil reset_draw_depth(Entity self)` -[CallbackId](#Aliases) | [set_pre_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_friction) | Hooks before the virtual function.
The callback signature is `optional friction(Entity self)` -[CallbackId](#Aliases) | [set_post_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_friction) | Hooks after the virtual function.
The callback signature is `nil friction(Entity self)` +[CallbackId](#Aliases) | [set_pre_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_friction) | Hooks before the virtual function.
The callback signature is `optional friction(Entity self)`
Virtual function docs:
Friction of this entity, affects it's contact with other entities (how fast it slows down on the floor, how fast it can move but also the other way around for floors/activefloors: how other entities can move on it) +[CallbackId](#Aliases) | [set_post_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_friction) | Hooks after the virtual function.
The callback signature is `nil friction(Entity self)`
Virtual function docs:
Friction of this entity, affects it's contact with other entities (how fast it slows down on the floor, how fast it can move but also the other way around for floors/activefloors: how other entities can move on it) [CallbackId](#Aliases) | [set_pre_set_as_sound_source(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_set_as_sound_source) | Hooks before the virtual function.
The callback signature is `bool set_as_sound_source(Entity self, SoundMeta soundmeta)` [CallbackId](#Aliases) | [set_post_set_as_sound_source(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_set_as_sound_source) | Hooks after the virtual function.
The callback signature is `nil set_as_sound_source(Entity self, SoundMeta soundmeta)` -[CallbackId](#Aliases) | [set_pre_remove_item(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_remove_item) | Hooks before the virtual function.
The callback signature is `bool remove_item(Entity self, Entity entity, bool autokill_check)` -[CallbackId](#Aliases) | [set_post_remove_item(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_remove_item) | Hooks after the virtual function.
The callback signature is `nil remove_item(Entity self, Entity entity, bool autokill_check)` +[CallbackId](#Aliases) | [set_pre_remove_item(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_remove_item) | Hooks before the virtual function.
The callback signature is `bool remove_item(Entity self, Entity entity, bool autokill_check)`
Virtual function docs:
Can be called multiple times for the same entity (for example when play throws/drops entity from it's hands) +[CallbackId](#Aliases) | [set_post_remove_item(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_remove_item) | Hooks after the virtual function.
The callback signature is `nil remove_item(Entity self, Entity entity, bool autokill_check)`
Virtual function docs:
Can be called multiple times for the same entity (for example when play throws/drops entity from it's hands) [CallbackId](#Aliases) | [set_pre_get_held_entity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_held_entity) | Hooks before the virtual function.
The callback signature is `optional get_held_entity(Entity self)` [CallbackId](#Aliases) | [set_post_get_held_entity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_held_entity) | Hooks after the virtual function.
The callback signature is `nil get_held_entity(Entity self)` [CallbackId](#Aliases) | [set_pre_trigger_action(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_trigger_action) | Hooks before the virtual function.
The callback signature is `optional trigger_action(Entity self, Entity user)`
Virtual function docs:
Triggers weapons and other held items like teleporter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) @@ -4333,8 +4334,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_ledge_grab(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_ledge_grab) | Hooks after the virtual function.
The callback signature is `nil ledge_grab(Entity self, Entity who)` [CallbackId](#Aliases) | [set_pre_stood_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stood_on) | Hooks before the virtual function.
The callback signature is `bool stood_on(Entity self, Entity entity Vec2)` [CallbackId](#Aliases) | [set_post_stood_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stood_on) | Hooks after the virtual function.
The callback signature is `nil stood_on(Entity self, Entity entity Vec2)` -[CallbackId](#Aliases) | [set_pre_liberate_from_shop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_liberate_from_shop) | Hooks before the virtual function.
The callback signature is `bool liberate_from_shop(Entity self, bool clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 -[CallbackId](#Aliases) | [set_post_liberate_from_shop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_liberate_from_shop) | Hooks after the virtual function.
The callback signature is `nil liberate_from_shop(Entity self, bool clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 +[CallbackId](#Aliases) | [set_pre_liberate_from_shop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_liberate_from_shop) | Hooks before the virtual function.
The callback signature is `bool liberate_from_shop(Entity self, bool clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought +[CallbackId](#Aliases) | [set_post_liberate_from_shop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_liberate_from_shop) | Hooks after the virtual function.
The callback signature is `nil liberate_from_shop(Entity self, bool clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought [CallbackId](#Aliases) | [set_pre_init(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_init) | Hooks before the virtual function.
The callback signature is `bool init(Entity self)` [CallbackId](#Aliases) | [set_post_init(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_init) | Hooks after the virtual function.
The callback signature is `nil init(Entity self)` @@ -5513,6 +5514,11 @@ bool | [has_powerup(ENT_TYPE powerup_type)](https://github.com/spelunky-fyi/over vector<[ENT_TYPE](#ENT_TYPE)> | [get_powerups()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_powerups) | Return all powerups that the entity has nil | [unequip_backitem()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=unequip_backitem) | Unequips the currently worn backitem int | [worn_backitem()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=worn_backitem) | Returns the uid of the currently worn backitem, or -1 if wearing nothing +[CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. +[CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. +nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. +[CallbackId](#Aliases) | [set_pre_blood_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_blood_collision) | Hooks before the virtual function.
The callback signature is `optional blood_collision(PowerupCapable self)` +[CallbackId](#Aliases) | [set_post_blood_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_blood_collision) | Hooks after the virtual function.
The callback signature is `nil blood_collision(PowerupCapable self)` ### ProtoShopkeeper @@ -5902,7 +5908,7 @@ float | [distance_after_capture](https://github.com/spelunky-fyi/overlunky/searc ### Backpack -Derived from [Entity](#Entity) [Movable](#Movable) +Derived from [Entity](#Entity) [Movable](#Movable) [Powerup](#Powerup) Type | Name | Description @@ -5910,6 +5916,11 @@ Type | Name | Description bool | [explosion_trigger](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=explosion_trigger) | More like on fire trigger, the explosion happens when the timer reaches > 29 int | [explosion_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=explosion_timer) | nil | [trigger_explosion()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=trigger_explosion) | +[CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. +[CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. +nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. +[CallbackId](#Aliases) | [set_pre_trigger_explosion(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_trigger_explosion) | Hooks before the virtual function.
The callback signature is `bool trigger_explosion(Backpack self)` +[CallbackId](#Aliases) | [set_post_trigger_explosion(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_trigger_explosion) | Hooks after the virtual function.
The callback signature is `nil trigger_explosion(Backpack self)` ### Birdies @@ -6009,7 +6020,7 @@ int | [seen](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=seen) | The callback signature is `bool trigger_explosion(DummyPurchasableEntity self, Entity who)`
Virtual function docs:
Transfers ownership etc. for who to blame, sets the exploding bool +[CallbackId](#Aliases) | [set_post_trigger_explosion(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_trigger_explosion) | Hooks after the virtual function.
The callback signature is `nil trigger_explosion(DummyPurchasableEntity self, Entity who)`
Virtual function docs:
Transfers ownership etc. for who to blame, sets the exploding bool ### EggSac @@ -6714,7 +6730,7 @@ int | [wiggle_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=wi ### Hoverpack -Derived from [Entity](#Entity) [Movable](#Movable) [Backpack](#Backpack) +Derived from [Entity](#Entity) [Movable](#Movable) [Powerup](#Powerup) [Backpack](#Backpack) Type | Name | Description @@ -6745,7 +6761,7 @@ float | [spawn_y](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn ### Jetpack -Derived from [Entity](#Entity) [Movable](#Movable) [Backpack](#Backpack) +Derived from [Entity](#Entity) [Movable](#Movable) [Powerup](#Powerup) [Backpack](#Backpack) Type | Name | Description @@ -6753,6 +6769,11 @@ Type | Name | Description bool | [flame_on](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=flame_on) | int | [fuel](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=fuel) | float | [acceleration()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=acceleration) | +[CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. +[CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. +nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. +[CallbackId](#Aliases) | [set_pre_acceleration(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_acceleration) | Hooks before the virtual function.
The callback signature is `optional acceleration(Jetpack self)` +[CallbackId](#Aliases) | [set_post_acceleration(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_acceleration) | Hooks after the virtual function.
The callback signature is `nil acceleration(Jetpack self)` ### JungleSpearCosmetic @@ -6975,11 +6996,11 @@ nil | [reset_gravity()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q nil | [set_position(float to_x, float to_y)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_position) | Set the absolute position of an entity and offset all rendering related things accordingly to teleport without any interpolation or graphical glitches. If the camera is focused on the entity, it is also moved. nil | [process_input()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=process_input) | float | [calculate_jump_velocity(bool dont_ignore_liquid)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=calculate_jump_velocity) | -nil | [apply_velocity(Vec2 velocities, bool ignore_weight)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apply_velocity) | +nil | [apply_velocity(Vec2 velocities, bool ignore_weight)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=apply_velocity) | Mostly used for ragdoll by the game int | [get_damage()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_damage) | Returns the damage that the entity deals bool | [attack(Entity victim)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=attack) | Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) bool | [thrown_into(Entity victim)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=thrown_into) | Same as above, but for being thrown into something and potentially dealing damage that way -int | [get_damage_sound(DAMAGE_TYPE damage)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_damage_sound) | returns sound id for the damage taken, return 0 to make it silence +[SOUNDID](#Aliases) | [get_damage_sound(DAMAGE_TYPE damage)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_damage_sound) | returns sound id for the damage taken, return 0 to make it silence nil | [copy_extra_info(Entity clone, int some_entity_uid)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=copy_extra_info) | Entities must be of the same type! [CutsceneBehavior](#CutsceneBehavior) | [cutscene](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=cutscene) | nil | [clear_cutscene()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_cutscene) | @@ -6995,16 +7016,12 @@ nil | [generic_update_world(Vec2 move, float sprint_factor, bool disable_gravity nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. [CallbackId](#Aliases) | [set_pre_can_jump(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_can_jump) | Hooks before the virtual function.
The callback signature is `optional can_jump(Movable self)`
Virtual function docs:
Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. [CallbackId](#Aliases) | [set_post_can_jump(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_can_jump) | Hooks after the virtual function.
The callback signature is `nil can_jump(Movable self)`
Virtual function docs:
Return true if the entity is allowed to jump, even midair. Return false and can't jump, except from ladders apparently. -[CallbackId](#Aliases) | [set_pre_get_collision_info(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_collision_info) | Hooks before the virtual function.
The callback signature is `bool get_collision_info(Movable self, CollisionInfo dest)` -[CallbackId](#Aliases) | [set_post_get_collision_info(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_collision_info) | Hooks after the virtual function.
The callback signature is `nil get_collision_info(Movable self, CollisionInfo dest)` [CallbackId](#Aliases) | [set_pre_sprint_factor(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_sprint_factor) | Hooks before the virtual function.
The callback signature is `optional sprint_factor(Movable self)` [CallbackId](#Aliases) | [set_post_sprint_factor(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_sprint_factor) | Hooks after the virtual function.
The callback signature is `nil sprint_factor(Movable self)` [CallbackId](#Aliases) | [set_pre_calculate_jump_velocity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_calculate_jump_velocity) | Hooks before the virtual function.
The callback signature is `optional calculate_jump_velocity(Movable self, bool dont_ignore_liquid)` [CallbackId](#Aliases) | [set_post_calculate_jump_velocity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_calculate_jump_velocity) | Hooks after the virtual function.
The callback signature is `nil calculate_jump_velocity(Movable self, bool dont_ignore_liquid)` -[CallbackId](#Aliases) | [set_pre_get_animation_map(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_animation_map) | Hooks before the virtual function.
The callback signature is `optional> get_animation_map(Movable self)` -[CallbackId](#Aliases) | [set_post_get_animation_map(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_animation_map) | Hooks after the virtual function.
The callback signature is `nil get_animation_map(Movable self)` -[CallbackId](#Aliases) | [set_pre_apply_velocity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_apply_velocity) | Hooks before the virtual function.
The callback signature is `bool apply_velocity(Movable self, Vec2 velocities, bool ignore_weight)` -[CallbackId](#Aliases) | [set_post_apply_velocity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_apply_velocity) | Hooks after the virtual function.
The callback signature is `nil apply_velocity(Movable self, Vec2 velocities, bool ignore_weight)` +[CallbackId](#Aliases) | [set_pre_apply_velocity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_apply_velocity) | Hooks before the virtual function.
The callback signature is `bool apply_velocity(Movable self, Vec2 velocities, bool ignore_weight)`
Virtual function docs:
Mostly used for ragdoll by the game +[CallbackId](#Aliases) | [set_post_apply_velocity(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_apply_velocity) | Hooks after the virtual function.
The callback signature is `nil apply_velocity(Movable self, Vec2 velocities, bool ignore_weight)`
Virtual function docs:
Mostly used for ragdoll by the game [CallbackId](#Aliases) | [set_pre_get_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_damage) | Hooks before the virtual function.
The callback signature is `optional get_damage(Movable self)`
Virtual function docs:
Returns the damage that the entity deals [CallbackId](#Aliases) | [set_post_get_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_damage) | Hooks after the virtual function.
The callback signature is `nil get_damage(Movable self)`
Virtual function docs:
Returns the damage that the entity deals [CallbackId](#Aliases) | [set_pre_is_on_fire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_is_on_fire) | Hooks before the virtual function.
The callback signature is `optional is_on_fire(Movable self)` @@ -7017,7 +7034,7 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_damage) | Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer [CallbackId](#Aliases) | [set_pre_on_hit(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_on_hit) | Hooks before the virtual function.
The callback signature is `bool on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. [CallbackId](#Aliases) | [set_post_on_hit(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_on_hit) | Hooks after the virtual function.
The callback signature is `nil on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. -[CallbackId](#Aliases) | [set_pre_get_damage_sound(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_damage_sound) | Hooks before the virtual function.
The callback signature is `optional get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence +[CallbackId](#Aliases) | [set_pre_get_damage_sound(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_damage_sound) | Hooks before the virtual function.
The callback signature is `optional get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence [CallbackId](#Aliases) | [set_post_get_damage_sound(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_damage_sound) | Hooks after the virtual function.
The callback signature is `nil get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence [CallbackId](#Aliases) | [set_pre_stun(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stun) | Hooks before the virtual function.
The callback signature is `bool stun(Movable self, int framecount)` [CallbackId](#Aliases) | [set_post_stun(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stun) | Hooks after the virtual function.
The callback signature is `nil stun(Movable self, int framecount)` @@ -7073,8 +7090,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_break_block(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_break_block) | Hooks after the virtual function.
The callback signature is `nil break_block(Movable self, bool camera_shake, Entity block)` [CallbackId](#Aliases) | [set_pre_crush(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_crush) | Hooks before the virtual function.
The callback signature is `bool crush(Movable self, Entity entity)` [CallbackId](#Aliases) | [set_post_crush(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_crush) | Hooks after the virtual function.
The callback signature is `nil crush(Movable self, Entity entity)` -[CallbackId](#Aliases) | [set_pre_instakill_death(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_instakill_death) | Hooks before the virtual function.
The callback signature is `bool instakill_death(Movable self)` -[CallbackId](#Aliases) | [set_post_instakill_death(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_instakill_death) | Hooks after the virtual function.
The callback signature is `nil instakill_death(Movable self)` +[CallbackId](#Aliases) | [set_pre_body_destruction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_body_destruction) | Hooks before the virtual function.
The callback signature is `bool body_destruction(Movable self)` +[CallbackId](#Aliases) | [set_post_body_destruction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_body_destruction) | Hooks after the virtual function.
The callback signature is `nil body_destruction(Movable self)` ### MovingIcon @@ -7113,6 +7130,11 @@ Type | Name | Description int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) | int | [bombs_left](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=bombs_left) | nil | [spawn_projectile()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_projectile) | +[CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. +[CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. +nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. +[CallbackId](#Aliases) | [set_pre_spawn_projectile(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_spawn_projectile) | Hooks before the virtual function.
The callback signature is `bool spawn_projectile(OlmecCannon self)` +[CallbackId](#Aliases) | [set_post_spawn_projectile(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_spawn_projectile) | Hooks after the virtual function.
The callback signature is `nil spawn_projectile(OlmecCannon self)` ### OlmecFloater @@ -7202,6 +7224,13 @@ Derived from [Entity](#Entity) [Movable](#Movable) Type | Name | Description ---- | ---- | ----------- +[CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. +[CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. +nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. +[CallbackId](#Aliases) | [set_pre_putting_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_putting_on) | Hooks before the virtual function.
The callback signature is `bool putting_on(Powerup self, PowerupCapable who)` +[CallbackId](#Aliases) | [set_post_putting_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_putting_on) | Hooks after the virtual function.
The callback signature is `nil putting_on(Powerup self, PowerupCapable who)` +[CallbackId](#Aliases) | [set_pre_putting_off(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_putting_off) | Hooks before the virtual function.
The callback signature is `bool putting_off(Powerup self, PowerupCapable who)` +[CallbackId](#Aliases) | [set_post_putting_off(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_putting_off) | Hooks after the virtual function.
The callback signature is `nil putting_off(Powerup self, PowerupCapable who)` ### Present @@ -7250,6 +7279,11 @@ Derived from [Entity](#Entity) [Movable](#Movable) Type | Name | Description ---- | ---- | ----------- nil | [acquire(Entity who)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=acquire) | Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money +[CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. +[CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. +nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. +[CallbackId](#Aliases) | [set_pre_acquire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_acquire) | Hooks before the virtual function.
The callback signature is `bool acquire(Purchasable self, Entity who)`
Virtual function docs:
Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money +[CallbackId](#Aliases) | [set_post_acquire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_acquire) | Hooks after the virtual function.
The callback signature is `nil acquire(Purchasable self, Entity who)`
Virtual function docs:
Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money ### PushBlock @@ -7444,7 +7478,7 @@ int | [teleport_number](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q ### TeleporterBackpack -Derived from [Entity](#Entity) [Movable](#Movable) [Backpack](#Backpack) +Derived from [Entity](#Entity) [Movable](#Movable) [Powerup](#Powerup) [Backpack](#Backpack) Type | Name | Description @@ -7606,7 +7640,7 @@ Type | Name | Description ### VladsCape -Derived from [Entity](#Entity) [Movable](#Movable) [Backpack](#Backpack) [Cape](#Cape) +Derived from [Entity](#Entity) [Movable](#Movable) [Powerup](#Powerup) [Backpack](#Backpack) [Cape](#Cape) Type | Name | Description diff --git a/src/game_api/entities_chars.hpp b/src/game_api/entities_chars.hpp index c9ae9b5b2..9eadf6934 100644 --- a/src/game_api/entities_chars.hpp +++ b/src/game_api/entities_chars.hpp @@ -88,16 +88,13 @@ class PowerupCapable : public Movable /// Return all powerups that the entity has std::vector get_powerups(); - /// Unequips the currently worn backitem void unequip_backitem(); - /// Returns the uid of the currently worn backitem, or -1 if wearing nothing int32_t worn_backitem(); - // those could be wrong because of the update - virtual bool on_blood_collision() = 0; // only triggers when player has kapala - + /// only triggers when it has kapala + virtual bool on_blood_collision() = 0; // called for stunned entities, check bunch of stuff like state, hold entity, standing on entity etc. runs until returned 1 // this is used to clear the last_owner of stunned entity when it is no longed stunned virtual bool can_clear_last_owner() = 0; diff --git a/src/game_api/entities_items.hpp b/src/game_api/entities_items.hpp index fd68c8f2b..ad8855ac0 100644 --- a/src/game_api/entities_items.hpp +++ b/src/game_api/entities_items.hpp @@ -25,9 +25,11 @@ class Powerup : public Movable // not sure why the normal powerups use apply/remove effect where backpacks use the put on/put off virtual void apply_effect(PowerupCapable* who) = 0; virtual void remove_effect(PowerupCapable* who) = 0; // does not remove powerup from the powerups map + /// only for backpacks virtual void on_putting_on(PowerupCapable* who) = 0; // only for backpacks, sets offsets etc. + /// only for backpacks virtual void on_putting_off(PowerupCapable* who) = 0; - /// for jetpack returns jetpack.flame_on, for capes Cape.floating_down, for hoverpack hoverpack.is_on, teleporter and powerpack and all other powerups return false + /// for jetpack returns jetpack.flame_on, for capes Cape.floating_down, for hoverpack hoverpack.is_on, teleporter, powerpack and all other powerups return false virtual bool in_use() = 0; }; @@ -40,7 +42,7 @@ class Backpack : public Powerup uint16_t unknown1; uint32_t unknown2; - virtual void trigger_explosion() = 0; // Causes the backpack to play its warning sound and triggers the explosion + virtual void trigger_explosion() = 0; }; class Jetpack : public Backpack diff --git a/src/game_api/entities_monsters.hpp b/src/game_api/entities_monsters.hpp index 7ffa04fd8..2e4eaeddd 100644 --- a/src/game_api/entities_monsters.hpp +++ b/src/game_api/entities_monsters.hpp @@ -582,7 +582,7 @@ class Anubis : public Monster virtual void set_next_attack_timer() = 0; // sets next_attack_timer based on the psychic_orbs_counter virtual void normal_attack() = 0; - virtual void play_attack_sound() = 0; // also calls virtual 20 + virtual void play_attack_sound() = 0; }; class Cobra : public Monster diff --git a/src/game_api/entities_mounts.hpp b/src/game_api/entities_mounts.hpp index 77e0cb739..e200e99c3 100644 --- a/src/game_api/entities_mounts.hpp +++ b/src/game_api/entities_mounts.hpp @@ -42,7 +42,8 @@ class Mount : public PowerupCapable virtual SOUNDID get_mounting_sound() = 0; // 103 virtual SOUNDID get_walking_sound() = 0; // 104 virtual SOUNDID get_untamed_loop_sound() = 0; // 105 - virtual bool can_play_mount_sound() = 0; // 106, called every frame, if returns true mount will make a sound + /// called every frame, if returns true mount will make a sound + virtual bool can_play_mount_sound() = 0; // 106 }; class Rockdog : public Mount diff --git a/src/game_api/entity.hpp b/src/game_api/entity.hpp index 1ac46d991..e9fbb4e73 100644 --- a/src/game_api/entity.hpp +++ b/src/game_api/entity.hpp @@ -287,22 +287,24 @@ class Entity /// Completely removes the entity from existence virtual void destroy() = 0; // 5 - virtual void apply_texture(Texture*) = 0; // 6 - virtual void format_shopitem_name(char16_t*) = 0; // 7 - virtual void generate_stomp_damage_particles(Entity* victim, DAMAGE_TYPE damage, bool) = 0; // 8, particles when jumping on top of enemy - virtual float get_type_field_a8() = 0; // 9 - virtual bool can_be_pushed() = 0; // 10, (runs only for activefloors?) checks if entity type is pushblock, for chained push block checks ChainedPushBlock.is_chained, is only a check that allows for the pushing animation - virtual bool v11() = 0; // 11, is in motion? (only projectiles and some weapons) + virtual void apply_texture(Texture*) = 0; // 6 + virtual void format_shopitem_name(char16_t* output) = 0; // 7 + virtual void generate_damage_particles(Entity* victim, DAMAGE_TYPE damage, bool killing) = 0; // 8, contact dmg + virtual float get_type_field_a8() = 0; // 9 + virtual bool can_be_pushed() = 0; // 10, (runs only for activefloors?) checks if entity type is pushblock, for chained push block checks ChainedPushBlock.is_chained, is only a check that allows for the pushing animation + virtual bool v11() = 0; // 11, is in motion? (only projectiles and some weapons) /// Returns true if entity is in water/lava - virtual bool is_in_liquid() = 0; // 12, drill always returns false - virtual bool check_type_properties_flags_19() = 0; // 13, checks (properties_flags >> 0x12) & 1; for hermitcrab checks if he's invisible; can't get it to trigger - virtual uint8_t get_type_field_60() = 0; // 14, the value is compared to entity state and used in some behavior function - virtual void set_invisible(bool value) = 0; // 15 - virtual void flip(bool left) = 0; // 16 - virtual void set_draw_depth(uint8_t draw_depth, uint8_t b3f) = 0; // 17 - virtual void reset_draw_depth() = 0; // 18 - virtual float friction() = 0; // 19 - virtual void set_as_sound_source(SoundMeta*) = 0; // 20, update sound position to entity position? + virtual bool is_in_liquid() = 0; // 12, drill always returns false + virtual bool check_type_properties_flags_19() = 0; // 13, checks (properties_flags >> 0x12) & 1; for hermitcrab checks if he's invisible; can't get it to trigger + virtual uint8_t get_type_field_60() = 0; // 14, the value is compared to entity state and used in some behavior function + virtual void set_invisible(bool value) = 0; // 15 + virtual void flip(bool left) = 0; // 16 + virtual void set_draw_depth(uint8_t draw_depth, uint8_t b3f) = 0; // 17 + virtual void reset_draw_depth() = 0; // 18 + /// Friction of this entity, affects it's contact with other entities (how fast it slows down on the floor, how fast it can move but also the other way around for floors/activefloors: how other entities can move on it) + virtual float friction() = 0; // 19 + virtual void set_as_sound_source(SoundMeta*) = 0; // 20, update sound position to entity position? + /// Can be called multiple times for the same entity (for example when play throws/drops entity from it's hands) virtual void remove_item(Entity* entity, bool autokill_check) = 0; // 21, if autokill_check is true, it will check if the entity has the "kill if overlay lost" flag and kill it if it's set virtual Entity* get_held_entity() = 0; // 22 virtual void v23(Entity* logical_trigger, Entity* who_triggered_it) = 0; // 23, spawns LASERTRAP_SHOT from LASERTRAP, also some trigger entities use this, seam to be called right after "on_collision2", triggers use self as the first parameter. Called when there is entity overlapping trigger entity, even if they don't move @@ -324,7 +326,7 @@ class Entity /// only for CHAR_*: when going to the backlayer, turns on/off player emitted light virtual void toggle_backlayer_illumination() = 0; // 33 virtual void v34() = 0; // 34, only ITEM_TORCH, calls Torch.light_up(false), can't get it to trigger - /// `clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1 + /// `clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought virtual void liberate_from_shop(bool clear_parrent) = 0; // 35, can also be seen as event: when you anger the shopkeeper, this function gets called for each item; can be called on shopitems individually as well and they become 'purchased' /// Applies changes made in `entity.type` diff --git a/src/game_api/entity_db.hpp b/src/game_api/entity_db.hpp index a17bf20ed..5a82eec41 100644 --- a/src/game_api/entity_db.hpp +++ b/src/game_api/entity_db.hpp @@ -106,8 +106,8 @@ struct EntityDB uint8_t field_9A; uint8_t field_9B; STRINGID description; - int32_t sound_killed_by_player; - int32_t sound_killed_by_other; + SOUNDID sound_killed_by_player; + SOUNDID sound_killed_by_other; float field_a8; int32_t field_AC; game_unordered_map> animations; diff --git a/src/game_api/layer.cpp b/src/game_api/layer.cpp index b2d0481d7..eae4b6419 100644 --- a/src/game_api/layer.cpp +++ b/src/game_api/layer.cpp @@ -83,8 +83,6 @@ Entity* Layer::spawn_entity_over(ENT_TYPE id, Entity* overlay, float x, float y) static auto spawn_entity_raw = (SpawnEntityFun*)get_address("spawn_entity"); using AddToLayer = void(Layer*, Entity*); static auto add_to_layer = (AddToLayer*)get_address("add_to_layer"); - using AddItemPtr = void(Entity*, Entity*, bool); - static auto add_item_ptr = (AddItemPtr*)get_address("add_item_ptr"); Entity* ent = spawn_entity_raw(entity_factory(), id, x, y, is_back_layer, overlay, true); diff --git a/src/game_api/movable.hpp b/src/game_api/movable.hpp index 84da52ead..0b80849b7 100644 --- a/src/game_api/movable.hpp +++ b/src/game_api/movable.hpp @@ -144,10 +144,11 @@ class Movable : public Entity virtual float sprint_factor() = 0; // 39, from entityDB virtual float calculate_jump_velocity(bool dont_ignore_liquid) = 0; // 40 virtual std::unordered_map& get_animation_map() = 0; // 41 - virtual void apply_velocity(Vec2& velocities, bool ignore_weight) = 0; // 42 + /// Mostly used for ragdoll by the game + virtual void apply_velocity(Vec2& velocities, bool ignore_weight) = 0; // 42 /// Returns the damage that the entity deals virtual int8_t get_damage() = 0; // 43, for player it calculates stomp damages as that's the only damage that the player entity can deal, the "normal" damage is done by the whip - virtual int8_t get_stomp_damage() = 0; // 44, calls get_damage except for mech which always returns 3, runs on stomping enemy + virtual int8_t get_stomp_damage() = 0; // 44, calls get_damage except for mech which always returns 3, dunno what's the difference between this and get_damage virtual bool is_on_fire() = 0; // 45 /// Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) virtual bool attack(Entity* victim) = 0; // 46 @@ -161,17 +162,17 @@ class Movable : public Entity /// Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. virtual void on_hit(Entity* damage_dealer) = 0; // 49 /// returns sound id for the damage taken, return 0 to make it silence - virtual uint32_t get_damage_sound(DAMAGE_TYPE damage) = 0; // 50 - virtual void stun(uint16_t framecount) = 0; // 51 + virtual SOUNDID get_damage_sound(DAMAGE_TYPE damage) = 0; // 50 + virtual void stun(uint16_t framecount) = 0; // 51 /// Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time virtual void freeze(uint8_t framecount, bool ignore_lava) = 0; // 52 /// Does not damage entity - virtual void light_on_fire(uint8_t time) = 0; // 53 - virtual void set_cursed(bool b, bool effect) = 0; // 54 - virtual void on_spiderweb_collision(bool) = 0; // 55, the bool sets pause statemachine flag? needs testing - virtual void set_last_owner_uid_b127(Entity* owner) = 0; // 56, assigns player as last_owner_uid and also manipulates movable.b127 - virtual uint32_t get_last_owner_uid() = 0; // 57, for players, it checks !stunned && !frozen && !cursed && !has_overlay; for others: just returns last_owner_uid + virtual void light_on_fire(uint8_t time) = 0; // 53 + virtual void set_cursed(bool b, bool effect) = 0; // 54 + virtual void on_spiderweb_collision(bool) = 0; // 55, the bool sets pause statemachine flag? needs testing + virtual void set_last_owner_uid(Entity* owner) = 0; // 56, assigns entity as last_owner_uid and also manipulates movable.b127 + virtual uint32_t get_last_owner_uid() = 0; // 57, for players, it checks !stunned && !frozen && !cursed && !has_overlay; for others: just returns last_owner_uid /// Disable to not get killed outside level bounds. virtual void check_out_of_bounds() = 0; // 58, kills with the 'still falling' death cause, is called for any item/fx/mount/monster/player virtual void set_standing_on(int32_t entity_uid) = 0; // 59 @@ -212,5 +213,5 @@ class Movable : public Entity virtual bool v89(void*, void*, bool, bool default_return_flipped) = 0; // 89, triggers on item_rubble?, first parameter only tested if it's 0 for punishball, ignored in the rest, second parameter never used (leftover?) virtual void on_crushed_by(Entity*) = 0; // 90, e.g. crushed by elevator, punishball, pushblock, crushtrap (not quillback or boulder) virtual SoundMeta* on_fall_onto(SOUNDID play_sound_id, Entity* fell_on_entity) = 0; // 91, plays the sfx at the entity and sets sound parameters - virtual void on_instakill_death() = 0; // 92, seems to only trigger for enemies that die in one hit, creates some big struct on stack, feeds it to some unknown function + virtual void on_body_destruction() = 0; // 92, creates some big struct on stack, feeds it to some unknown function }; diff --git a/src/game_api/script/usertypes/entities_items_lua.cpp b/src/game_api/script/usertypes/entities_items_lua.cpp index fc15183b8..29d4230c7 100644 --- a/src/game_api/script/usertypes/entities_items_lua.cpp +++ b/src/game_api/script/usertypes/entities_items_lua.cpp @@ -146,7 +146,7 @@ void register_usertypes(sol::state& lua) "trigger_explosion", &Backpack::trigger_explosion, sol::base_classes, - sol::bases()); + sol::bases()); lua.new_usertype( "Projectile", @@ -196,14 +196,14 @@ void register_usertypes(sol::state& lua) "acceleration", &Jetpack::acceleration, sol::base_classes, - sol::bases()); + sol::bases()); lua.new_usertype( "TeleporterBackpack", "teleport_number", &TeleporterBackpack::teleport_number, sol::base_classes, - sol::bases()); + sol::bases()); lua.new_usertype( "Hoverpack", @@ -212,11 +212,11 @@ void register_usertypes(sol::state& lua) "is_on", &Hoverpack::is_on, sol::base_classes, - sol::bases()); + sol::bases()); - lua.new_usertype("Cape", "floating_down", &Cape::floating_down, sol::base_classes, sol::bases()); + lua.new_usertype("Cape", "floating_down", &Cape::floating_down, sol::base_classes, sol::bases()); - lua.new_usertype("VladsCape", "can_double_jump", &VladsCape::can_double_jump, sol::base_classes, sol::bases()); + lua.new_usertype("VladsCape", "can_double_jump", &VladsCape::can_double_jump, sol::base_classes, sol::bases()); lua.new_usertype( "Mattock", diff --git a/src/game_api/script/usertypes/entity_lua.cpp b/src/game_api/script/usertypes/entity_lua.cpp index 25314e846..1274737a3 100644 --- a/src/game_api/script/usertypes/entity_lua.cpp +++ b/src/game_api/script/usertypes/entity_lua.cpp @@ -243,6 +243,7 @@ void register_usertypes(sol::state& lua) entity_type["set_draw_depth"] = set_draw_depth; entity_type["reset_draw_depth"] = &Entity::reset_draw_depth; + entity_type["friction"] = &Entity::friction; entity_type["set_enable_turning"] = &Entity::set_enable_turning; auto liberate_from_shop = sol::overload(&Entity::liberate_from_shop, [](Entity& ent) // for backward compatibility) diff --git a/src/game_api/script/usertypes/vtables_lua.cpp b/src/game_api/script/usertypes/vtables_lua.cpp index a775883ce..87af1ede9 100644 --- a/src/game_api/script/usertypes/vtables_lua.cpp +++ b/src/game_api/script/usertypes/vtables_lua.cpp @@ -1,5 +1,7 @@ #include "vtables_lua.hpp" +#include "entities_chars.hpp" // for PowerupCapable +#include "entities_items.hpp" // for Powerup and more ... #include "entity.hpp" // for Entity #include "entity_structs.hpp" // for CollisionInfo #include "hookable_vtable.hpp" // for HookableVTable @@ -30,9 +32,15 @@ void register_usertypes(sol::state& lua) VTableEntry<"kill", 3, MemFun<&Entity::kill>>, VTableEntry<"on_collision1", 4, MemFun<&Entity::on_collision1>>, VTableEntry<"destroy", 5, MemFun<&Entity::destroy>>, - VTableEntry<"generate_stomp_damage_particles", 8, MemFun<&Entity::generate_stomp_damage_particles>>, + // apply_texture + // format_shopitem_name // can't edit the string from lua unless i make so special type for it + VTableEntry<"generate_damage_particles", 8, MemFun<&Entity::generate_damage_particles>>, + // get_type_field_a8 VTableEntry<"can_be_pushed", 10, MemFun<&Entity::can_be_pushed>>, + // v11 VTableEntry<"is_in_liquid", 12, MemFun<&Entity::is_in_liquid>>, + // check_type_properties_flags_19 + // get_type_field_60 VTableEntry<"set_invisible", 15, MemFun<&Entity::set_invisible>>, VTableEntry<"flip", 16, MemFun<&Entity::flip>>, VTableEntry<"set_draw_depth", 17, MemFun<&Entity::set_draw_depth>>, @@ -41,6 +49,7 @@ void register_usertypes(sol::state& lua) VTableEntry<"set_as_sound_source", 20, MemFun<&Entity::set_as_sound_source>>, VTableEntry<"remove_item", 21, MemFun<&Entity::remove_item>>, VTableEntry<"get_held_entity", 22, MemFun<&Entity::get_held_entity>>, + // v23 VTableEntry<"trigger_action", 24, MemFun<&Entity::trigger_action>>, VTableEntry<"activate", 25, MemFun<&Entity::activate>>, VTableEntry<"on_collision2", 26, MemFun<&Entity::on_collision2>>, @@ -50,6 +59,8 @@ void register_usertypes(sol::state& lua) VTableEntry<"walked_off", 30, MemFun<&Entity::on_walked_off_by>>, VTableEntry<"ledge_grab", 31, MemFun<&Entity::on_ledge_grab>>, VTableEntry<"stood_on", 32, MemFun<&Entity::on_stood_on_by>>, + // toggle_backlayer_illumination + // v34 VTableEntry<"liberate_from_shop", 35, MemFun<&Entity::liberate_from_shop>>, VTableEntry<"init", 36, MemFun<&Entity::apply_db>>>; static EntityVTable entity_vtable(lua, lua["Entity"], "ENTITY_OVERRIDE"); @@ -59,14 +70,15 @@ void register_usertypes(sol::state& lua) CallbackType::Entity, EntityVTable, VTableEntry<"can_jump", 37, MemFun<&Movable::can_jump>>, - VTableEntry<"get_collision_info", 38, MemFun<&Movable::get_collision_info>>, + // <"get_collision_info", 38, MemFun<&Movable::get_collision_info>>, // dunno if it works, or if it's even called by the game VTableEntry<"sprint_factor", 39, MemFun<&Movable::sprint_factor>>, VTableEntry<"calculate_jump_velocity", 40, MemFun<&Movable::calculate_jump_velocity>>, - // VTableEntry<"get_animation_map", 41, MemFun<&Movable::get_animation_map>>, + // <"get_animation_map", 41, MemFun<&Movable::get_animation_map>>, VTableEntry<"apply_velocity", 42, MemFun<&Movable::apply_velocity>>, /// NoDoc VTableEntry<"stomp_damage", 43, MemFun<&Movable::get_damage>>, VTableEntry<"get_damage", 43, MemFun<&Movable::get_damage>>, + // <"get_stomp_damage", 43, MemFun<&Movable::get_stomp_damage>>, // still don't know the difference between this and get_damage VTableEntry<"is_on_fire", 45, MemFun<&Movable::is_on_fire>>, VTableEntry<"attack", 46, MemFun<&Movable::attack>>, VTableEntry<"thrown_into", 47, MemFun<&Movable::thrown_into>>, @@ -78,12 +90,17 @@ void register_usertypes(sol::state& lua) VTableEntry<"light_on_fire", 53, MemFun<&Movable::light_on_fire>>, VTableEntry<"set_cursed", 54, MemFun<&Movable::set_cursed>>, VTableEntry<"web_collision", 55, MemFun<&Movable::on_spiderweb_collision>>, + // set_last_owner_uid + // get_last_owner_uid VTableEntry<"check_out_of_bounds", 58, MemFun<&Movable::check_out_of_bounds>>, VTableEntry<"set_standing_on", 59, MemFun<&Movable::set_standing_on>>, VTableEntry<"standing_on", 60, MemFun<&Movable::standing_on>>, VTableEntry<"stomped_by", 61, MemFun<&Movable::on_stomped_on_by>>, VTableEntry<"thrown_by", 62, MemFun<&Movable::on_thrown_by>>, VTableEntry<"cloned_to", 63, MemFun<&Movable::copy_extra_info>>, + // get_type_id + // doesnt_have_spikeshoes (potentially wrong name) + // is_player_mount_or_monster VTableEntry<"pick_up", 67, MemFun<&Movable::pick_up>>, /// NoDoc VTableEntry<"picked_up_by", 68, MemFun<&Movable::can_be_picked_up_by>>, @@ -91,9 +108,14 @@ void register_usertypes(sol::state& lua) VTableEntry<"drop", 69, MemFun<&Movable::drop>>, VTableEntry<"collect_treasure", 70, MemFun<&Movable::collect_treasure>>, VTableEntry<"apply_movement", 71, MemFun<&Movable::apply_movement>>, - VTableEntry<"is_powerup_capable", 74, MemFun<&Movable::is_powerup_capable>>, + // damage_entity + // v73 + VTableEntry<"is_powerup_capable", 74, MemFun<&Movable::is_powerup_capable>>, // dunno if called by the game, might be inlined? VTableEntry<"initialize", 75, MemFun<&Movable::initialize>>, + // check_is_falling + // v77 VTableEntry<"process_input", 78, MemFun<&Movable::process_input>>, + // post_collision_damage_related? VTableEntry<"picked_up", 80, MemFun<&Movable::on_picked_up>>, VTableEntry<"release", 81, MemFun<&Movable::on_release>>, VTableEntry<"generate_fall_poof_particles", 82, MemFun<&Movable::generate_fall_poof_particles>>, @@ -101,8 +123,12 @@ void register_usertypes(sol::state& lua) VTableEntry<"apply_friction", 84, MemFun<&Movable::apply_friction>>, VTableEntry<"can_break_block", 85, MemFun<&Movable::can_break_block>>, VTableEntry<"break_block", 86, MemFun<&Movable::break_block>>, + // v87 + // v88 + // v89 VTableEntry<"crush", 90, MemFun<&Movable::on_crushed_by>>, - VTableEntry<"instakill_death", 92, MemFun<&Movable::on_instakill_death>>>; + // on_fall_onto // interesting, needs testing + VTableEntry<"body_destruction", 92, MemFun<&Movable::on_body_destruction>>>; static MovableVTable movable_vtable(lua, lua["Movable"], "ENTITY_OVERRIDE"); using FloorVTable = HookableVTable< @@ -119,6 +145,7 @@ void register_usertypes(sol::state& lua) VTableEntry<"enter_attempt", 40, float(Entity*)>, VTableEntry<"hide_hud", 41, float(Entity*)>, VTableEntry<"enter", 42, uint8_t(Entity*)>, + // entered_from_front_layer VTableEntry<"light_level", 44, float()>, VTableEntry<"is_unlocked", 45, bool()>, VTableEntry<"can_enter", 46, bool(Entity*)>>; @@ -131,6 +158,75 @@ void register_usertypes(sol::state& lua) VTableEntry<"render", 0x3, void(float*), BackBinder>>; static RenderInfoVTable render_info_vtable(lua, lua["RenderInfo"], "RENDER_INFO_OVERRIDE"); + using PowerupCapableVTable = HookableVTable< + Entity, + CallbackType::Entity, + EntityVTable, + VTableEntry<"blood_collision", 93, MemFun<&PowerupCapable::on_blood_collision>>>; + // can_clear_last_owner + static PowerupCapableVTable powerup_capable_vtable(lua, lua["PowerupCapable"], "ENTITY_OVERRIDE"); + + using PowerupVTable = HookableVTable< + Entity, + CallbackType::Entity, + EntityVTable, + // <"get_hud_sprite", 93, MemFun<&Powerup::get_hud_sprite>>, + VTableEntry<"putting_on", 96, MemFun<&Powerup::on_putting_on>>, + VTableEntry<"putting_off", 97, MemFun<&Powerup::on_putting_off>>>; + static PowerupVTable powerup_vtable(lua, lua["Powerup"], "ENTITY_OVERRIDE"); + + using BackpackVTable = HookableVTable< + Entity, + CallbackType::Entity, + EntityVTable, + VTableEntry<"trigger_explosion", 99, MemFun<&Backpack::trigger_explosion>>>; + static BackpackVTable backpack_vtable(lua, lua["Backpack"], "ENTITY_OVERRIDE"); + + using JetpackVTable = HookableVTable< + Entity, + CallbackType::Entity, + EntityVTable, + VTableEntry<"acceleration", 100, MemFun<&Jetpack::acceleration>>>; + static JetpackVTable jetpack_vtable(lua, lua["Jetpack"], "ENTITY_OVERRIDE"); + + using PurchasableVTable = HookableVTable< + Entity, + CallbackType::Entity, + EntityVTable, + VTableEntry<"acquire", 93, MemFun<&Purchasable::acquire>>>; + static PurchasableVTable purchasable_vtable(lua, lua["Purchasable"], "ENTITY_OVERRIDE"); + + using DummyPurchasableEntityVTable = HookableVTable< + Entity, + CallbackType::Entity, + EntityVTable, + VTableEntry<"trigger_explosion", 94, MemFun<&DummyPurchasableEntity::trigger_explosion>>>; + static DummyPurchasableEntityVTable dummy_purchasable_entity_vtable(lua, lua["DummyPurchasableEntity"], "ENTITY_OVERRIDE"); + + using OlmecCannonVTable = HookableVTable< + Entity, + CallbackType::Entity, + EntityVTable, + VTableEntry<"spawn_projectile", 93, MemFun<&OlmecCannon::spawn_projectile>>>; + static OlmecCannonVTable olmec_cannon_vtable(lua, lua["OlmecCannon"], "ENTITY_OVERRIDE"); + + // Arrow // poison_arrow // light_up ? + // Torch // light_up // get_flame_offset // get_flame_type + // Bow // get_arrow_special_offset + // Generator // randomize_timer ? + // RollingItem // pickup + // SoundMeta // start // kill //update maybe? + // CritterSlime + CritterSnail // get_speed + // Ghist // on_body_destroyed + // YetiQueen + YetiKing // ?? + // Anubis // set_next_attack_timer // normal_attack // play_attack_sound + // Spider // ?? + // WalkingMonster // can_aggro + // NPC .... + // RoomOwner ... + // Monster ... + // Mount ... + // Define the implementations for the LuaBackend handlers HookHandler::set_hook_dtor_impl( [](std::uint32_t uid, std::function fun) diff --git a/src/game_api/sound_manager.hpp b/src/game_api/sound_manager.hpp index 230e2bfd4..c1c9eb66a 100644 --- a/src/game_api/sound_manager.hpp +++ b/src/game_api/sound_manager.hpp @@ -303,7 +303,7 @@ SoundMeta* play_sound(VANILLA_SOUND sound, uint32_t source_uid); SoundMeta* play_sound(SOUNDID sound_id, uint32_t source_uid); // could probably be exposed if someone can actually figure out how to properly "register it"? -// it also needs to make sure the lua owns the returned object and it will properly delete it +// it probably also needs to make sure the lua owns the returned object and it will properly delete it SoundMeta* construct_soundmeta(VANILLA_SOUND sound, bool background_sound); SoundMeta* construct_soundmeta(SOUNDID sound_id, bool background_sound); /* diff --git a/src/info_dump/main.cpp b/src/info_dump/main.cpp index 2d9250139..1f850bdf5 100644 --- a/src/info_dump/main.cpp +++ b/src/info_dump/main.cpp @@ -963,10 +963,10 @@ void get_vtables() const auto base_off = (size_t)Memory::get().exe(); - file << "TypeID,Name,vtable offset,~Entity,create_rendering_info,update_state_machine,kill,on_collision1,destroy,apply_texture,format_shopitem_name,generate_stomp_damage_particles,get_type_field_a8,can_be_pushed,v11,is_in_liquid,check_type_properties_flags_19,get_type_field_60,set_invisible,flip,set_draw_depth,reset_draw_depth,friction,set_as_sound_source,remove_item," + file << "TypeID,Name,vtable offset,~Entity,create_rendering_info,update_state_machine,kill,on_collision1,destroy,apply_texture,format_shopitem_name,generate_damage_particles,get_type_field_a8,can_be_pushed,v11,is_in_liquid,check_type_properties_flags_19,get_type_field_60,set_invisible,flip,set_draw_depth,reset_draw_depth,friction,set_as_sound_source,remove_item," "get_held_entity,v23,trigger_action,activate,on_collision2,get_metadata,apply_metadata,on_walked_on_by,on_walked_off_by,on_ledge_grab,on_stood_on_by,toggle_backlayer_illumination,v34,liberate_from_shop,apply_db,END OF ENTITY,can_jump,get_collision_info,sprint_factor,calculate_jump_velocity,get_animation_map,apply_velocity,get_damage,get_stomp_damage,is_on_fire,attack,thrown_into," "damage,on_hit,get_damage_sound,stun,freeze,light_on_fire,set_cursed,on_spiderweb_collision,set_last_owner_uid_b127,get_last_owner_uid,check_out_of_bounds,set_standing_on,standing_on,on_stomped_on_by,on_thrown_by,copy_extra_info,get_type_id,doesnt_have_spikeshoes,is_player_mount_or_monster,pick_up,can_be_picked_up_by,drop,collect_treasure,apply_movement,damage_entity,v73," - "is_powerup_capable,initialize,check_is_falling,v77,process_input,post_collision_damage_related,on_picked_up,on_release,generate_fall_poof_particles,handle_fall_logic,apply_friction,can_break_block,break_block,v87,v88,v89,on_crushed_by,on_fall_onto,on_instakill_death,END OF MOVABLE,v93,v94,v95,v96,v97,v98,v99,v100,v101,v102,v103,v104,v105,v106,v107,v108,v109,"; + "is_powerup_capable,initialize,check_is_falling,v77,process_input,post_collision_damage_related,on_picked_up,on_release,generate_fall_poof_particles,handle_fall_logic,apply_friction,can_break_block,break_block,v87,v88,v89,on_crushed_by,on_fall_onto,on_body_destruction,END OF MOVABLE,v93,v94,v95,v96,v97,v98,v99,v100,v101,v102,v103,v104,v105,v106,v107,v108,v109,"; file << std::endl; int idx = 0; @@ -987,6 +987,9 @@ void get_vtables() if (v_idx && base_functions.find(*(vtable_b + v_idx)) != base_functions.end()) break; + if (IsBadReadPtr((void*)(*(vtable_b + v_idx)), 8)) + break; + if (*(vtable_b + v_idx) == func_ret) { file << ",ret"; From cf38c6a99a33de06f28d75456e9a21b60318432a Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sat, 16 Nov 2024 13:24:31 +0100 Subject: [PATCH 13/21] typo --- docs/game_data/spel2.lua | 14 ++++++++++---- docs/src/includes/_types.md | 2 +- src/game_api/entities_items.hpp | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index d0d0a99ad..16ce78574 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -3844,7 +3844,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field set_post_trigger_explosion fun(self, fun: fun(self: DummyPurchasableEntity, who: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil trigger_explosion(DummyPurchasableEntity self, Entity who)`
Virtual function docs:
Transfers ownership etc. for who to blame, sets the exploding bool ---@class Bow : Purchasable - ---@field get_arrow_special_offset fun(self): number @When lying on the ground + ---@field get_arrow_special_offset fun(self): number @When laying on the ground ---@class Present : Purchasable ---@field inside ENT_TYPE @@ -7232,12 +7232,16 @@ DYNAMIC_TEXTURE = { } ---@alias DYNAMIC_TEXTURE integer ENTITY_OVERRIDE = { + ACCELERATION = 100, + ACQUIRE = 93, ACTIVATE = 25, APPLY_FRICTION = 84, APPLY_METADATA = 28, APPLY_MOVEMENT = 71, APPLY_VELOCITY = 42, ATTACK = 46, + BLOOD_COLLISION = 93, + BODY_DESTRUCTION = 92, BREAK_BLOCK = 86, CALCULATE_JUMP_VELOCITY = 40, CAN_BE_PICKED_UP_BY = 68, @@ -7261,9 +7265,8 @@ ENTITY_OVERRIDE = { FLOOR_UPDATE = 38, FREEZE = 52, FRICTION = 19, + GENERATE_DAMAGE_PARTICLES = 8, GENERATE_FALL_POOF_PARTICLES = 82, - GENERATE_STOMP_DAMAGE_PARTICLES = 8, - GET_COLLISION_INFO = 38, GET_DAMAGE = 43, GET_DAMAGE_SOUND = 50, GET_HELD_ENTITY = 22, @@ -7271,7 +7274,6 @@ ENTITY_OVERRIDE = { HIDE_HUD = 41, INIT = 36, INITIALIZE = 75, - INSTAKILL_DEATH = 92, IS_IN_LIQUID = 12, IS_ON_FIRE = 45, IS_POWERUP_CAPABLE = 74, @@ -7288,6 +7290,8 @@ ENTITY_OVERRIDE = { PICKED_UP_BY = 68, PICK_UP = 67, PROCESS_INPUT = 78, + PUTTING_OFF = 97, + PUTTING_ON = 96, RELEASE = 81, REMOVE_ITEM = 21, RESET_DRAW_DEPTH = 18, @@ -7296,6 +7300,7 @@ ENTITY_OVERRIDE = { SET_DRAW_DEPTH = 17, SET_INVISIBLE = 15, SET_STANDING_ON = 59, + SPAWN_PROJECTILE = 93, SPRINT_FACTOR = 39, STANDING_ON = 60, STOMPED_BY = 61, @@ -7305,6 +7310,7 @@ ENTITY_OVERRIDE = { THROWN_BY = 62, THROWN_INTO = 47, TRIGGER_ACTION = 24, + TRIGGER_EXPLOSION = 94, UPDATE_STATE_MACHINE = 2, WALKED_OFF = 30, WALKED_ON = 29, diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 0a70e91e8..4ab0606cf 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -5995,7 +5995,7 @@ Derived from [Entity](#Entity) [Movable](#Movable) [Purchasable](#Purchasable) Type | Name | Description ---- | ---- | ----------- -float | [get_arrow_special_offset()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_arrow_special_offset) | When lying on the ground +float | [get_arrow_special_offset()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_arrow_special_offset) | When laying on the ground ### Bullet diff --git a/src/game_api/entities_items.hpp b/src/game_api/entities_items.hpp index ad8855ac0..2ee033901 100644 --- a/src/game_api/entities_items.hpp +++ b/src/game_api/entities_items.hpp @@ -870,7 +870,7 @@ class PrizeDispenser : public Movable class Bow : public Purchasable { public: - /// When lying on the ground + /// When laying on the ground virtual float get_arrow_special_offset() = 0; }; From 02ae5831c3e18b8af7ab65af67e0b524137fb38f Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:21:11 +0100 Subject: [PATCH 14/21] add small comment --- src/game_api/level_api.hpp | 4 +--- src/game_api/online.hpp | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/game_api/level_api.hpp b/src/game_api/level_api.hpp index ef38e9c66..4735c1b44 100644 --- a/src/game_api/level_api.hpp +++ b/src/game_api/level_api.hpp @@ -254,9 +254,7 @@ class ThemeInfo uint32_t unknown3; uint32_t unknown4; - virtual ~ThemeInfo() - { - } + virtual ~ThemeInfo(){}; /// Sets the beehive and leprechaun flags virtual void reset_theme_flags() = 0; diff --git a/src/game_api/online.hpp b/src/game_api/online.hpp index 5e4b9cd8a..9159fa90b 100644 --- a/src/game_api/online.hpp +++ b/src/game_api/online.hpp @@ -102,6 +102,7 @@ class Online // some more stuff virtual ~Online() = 0; + // 27 virtuals, destructor probably at index 7 }; Online* get_online(); From fd154ab898ce2d3ec57e854337be8b5c67916d3c Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sun, 17 Nov 2024 23:51:12 +0100 Subject: [PATCH 15/21] bring back move semantics --- src/game_api/movable.hpp | 2 +- src/game_api/vtable_hook.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game_api/movable.hpp b/src/game_api/movable.hpp index 0b80849b7..cec678771 100644 --- a/src/game_api/movable.hpp +++ b/src/game_api/movable.hpp @@ -145,7 +145,7 @@ class Movable : public Entity virtual float calculate_jump_velocity(bool dont_ignore_liquid) = 0; // 40 virtual std::unordered_map& get_animation_map() = 0; // 41 /// Mostly used for ragdoll by the game - virtual void apply_velocity(Vec2& velocities, bool ignore_weight) = 0; // 42 + virtual void apply_velocity(Vec2* velocities, bool ignore_weight) = 0; // 42 /// Returns the damage that the entity deals virtual int8_t get_damage() = 0; // 43, for player it calculates stomp damages as that's the only damage that the player entity can deal, the "normal" damage is done by the whip virtual int8_t get_stomp_damage() = 0; // 44, calls get_damage except for mech which always returns 3, dunno what's the difference between this and get_damage diff --git a/src/game_api/vtable_hook.hpp b/src/game_api/vtable_hook.hpp index 67a8e5e03..3a77565b0 100644 --- a/src/game_api/vtable_hook.hpp +++ b/src/game_api/vtable_hook.hpp @@ -55,7 +55,7 @@ struct VTableDetour s_Functions[self](self, args..., s_Originals[vtable]); return; } - s_Originals[vtable](self, args...); + s_Originals[vtable](self, std::move(args)...); } else { From b10aebc9e14e05b1f8200a84ad62ed90a3d67f45 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:07:16 +0100 Subject: [PATCH 16/21] more comments --- docs/game_data/spel2.lua | 12 ++++++------ docs/src/includes/_types.md | 12 ++++++------ src/game_api/level_api.hpp | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index 16ce78574..d1a366caf 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -4740,13 +4740,13 @@ function MovableBehavior:get_state_id() end ---@field post_process_level fun(self): nil @Theme specific specialties like randomizing ushabti and Coco coffin location, spawns impostor lakes ---@field spawn_traps fun(self): nil @Spawns theme specific random traps, pushblocks and critters. Sets special exit doors. ---@field post_process_entities fun(self): nil @Fixes textures on pleasure palace ladders, adds some decorations - ---@field spawn_procedural fun(self): nil @Adds legs under platforms, random pots, goldbars, monsters, compass indicator, random shadows... + ---@field spawn_procedural fun(self): nil @Adds legs under platforms, random pots, goldbars, monsters, compass indicator, initialises quests, random shadows... ---@field spawn_background fun(self): nil @Adds the main level background , e.g. CO stars / Duat moon / Plain backwall for other themes ---@field spawn_lights fun(self): nil @Adds room lights to udjat chest room or black market ---@field spawn_transition fun(self): nil @Spawns the transition tunnel and players in it ---@field post_transition fun(self): nil @Handles loading the next level screen from a transition screen ---@field spawn_players fun(self): nil @Spawns the players with inventory at `state.level_gen.spawn_x/y`. Also shop and kali background and probably other stuff for some stupid reason. - ---@field spawn_effects fun(self): nil @Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. + ---@field spawn_effects fun(self): nil @Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. Spawns beg and handles it's quest flags ---@field get_level_file fun(self): string @Returns: The .lvl file to load (e.g. dwelling = dwellingarea.lvl except when level == 4 (cavebossarea.lvl)) ---@field get_theme_id fun(self): integer @Returns: THEME, or subtheme in CO ---@field get_base_id fun(self): integer @Returns: THEME, or logical base THEME for special levels (Abzu->Tide Pool etc) @@ -4813,8 +4813,8 @@ function MovableBehavior:get_state_id() end ---@field set_post_spawn_traps fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil spawn_traps(ThemeInfo self)`
Virtual function docs:
Spawns theme specific random traps, pushblocks and critters. Sets special exit doors. ---@field set_pre_post_process_entities fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool post_process_entities(ThemeInfo self)`
Virtual function docs:
Fixes textures on pleasure palace ladders, adds some decorations ---@field set_post_post_process_entities fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil post_process_entities(ThemeInfo self)`
Virtual function docs:
Fixes textures on pleasure palace ladders, adds some decorations - ---@field set_pre_spawn_procedural fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool spawn_procedural(ThemeInfo self)`
Virtual function docs:
Adds legs under platforms, random pots, goldbars, monsters, compass indicator, random shadows... - ---@field set_post_spawn_procedural fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil spawn_procedural(ThemeInfo self)`
Virtual function docs:
Adds legs under platforms, random pots, goldbars, monsters, compass indicator, random shadows... + ---@field set_pre_spawn_procedural fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool spawn_procedural(ThemeInfo self)`
Virtual function docs:
Adds legs under platforms, random pots, goldbars, monsters, compass indicator, initialises quests, random shadows... + ---@field set_post_spawn_procedural fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil spawn_procedural(ThemeInfo self)`
Virtual function docs:
Adds legs under platforms, random pots, goldbars, monsters, compass indicator, initialises quests, random shadows... ---@field set_pre_spawn_background fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool spawn_background(ThemeInfo self)`
Virtual function docs:
Adds the main level background , e.g. CO stars / Duat moon / Plain backwall for other themes ---@field set_post_spawn_background fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil spawn_background(ThemeInfo self)`
Virtual function docs:
Adds the main level background , e.g. CO stars / Duat moon / Plain backwall for other themes ---@field set_pre_spawn_lights fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool spawn_lights(ThemeInfo self)`
Virtual function docs:
Adds room lights to udjat chest room or black market @@ -4825,8 +4825,8 @@ function MovableBehavior:get_state_id() end ---@field set_post_post_transition fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil post_transition(ThemeInfo self)`
Virtual function docs:
Handles loading the next level screen from a transition screen ---@field set_pre_spawn_players fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool spawn_players(ThemeInfo self)`
Virtual function docs:
Spawns the players with inventory at `state.level_gen.spawn_x/y`. Also shop and kali background and probably other stuff for some stupid reason. ---@field set_post_spawn_players fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil spawn_players(ThemeInfo self)`
Virtual function docs:
Spawns the players with inventory at `state.level_gen.spawn_x/y`. Also shop and kali background and probably other stuff for some stupid reason. - ---@field set_pre_spawn_effects fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool spawn_effects(ThemeInfo self)`
Virtual function docs:
Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. - ---@field set_post_spawn_effects fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil spawn_effects(ThemeInfo self)`
Virtual function docs:
Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. + ---@field set_pre_spawn_effects fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool spawn_effects(ThemeInfo self)`
Virtual function docs:
Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. Spawns beg and handles it's quest flags + ---@field set_post_spawn_effects fun(self, fun: fun(self: ThemeInfo): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil spawn_effects(ThemeInfo self)`
Virtual function docs:
Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. Spawns beg and handles it's quest flags ---@field set_pre_theme_id fun(self, fun: fun(self: ThemeInfo): integer?): CallbackId @Hooks before the virtual function.
The callback signature is `optional theme_id(ThemeInfo self)` ---@field set_post_theme_id fun(self, fun: fun(self: ThemeInfo): integer?): CallbackId @Hooks after the virtual function.
The callback signature is `nil theme_id(ThemeInfo self)` ---@field set_pre_base_id fun(self, fun: fun(self: ThemeInfo): integer?): CallbackId @Hooks before the virtual function.
The callback signature is `optional base_id(ThemeInfo self)` diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 4ab0606cf..61ba1a419 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -3378,13 +3378,13 @@ nil | [spawn_border()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q= nil | [post_process_level()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=post_process_level) | Theme specific specialties like randomizing ushabti and Coco coffin location, spawns impostor lakes nil | [spawn_traps()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_traps) | Spawns theme specific random traps, pushblocks and critters. Sets special exit doors. nil | [post_process_entities()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=post_process_entities) | Fixes textures on pleasure palace ladders, adds some decorations -nil | [spawn_procedural()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_procedural) | Adds legs under platforms, random pots, goldbars, monsters, compass indicator, random shadows... +nil | [spawn_procedural()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_procedural) | Adds legs under platforms, random pots, goldbars, monsters, compass indicator, initialises quests, random shadows... nil | [spawn_background()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_background) | Adds the main level background , e.g. CO stars / Duat moon / Plain backwall for other themes nil | [spawn_lights()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_lights) | Adds room lights to udjat chest room or black market nil | [spawn_transition()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_transition) | Spawns the transition tunnel and players in it nil | [post_transition()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=post_transition) | Handles loading the next level screen from a transition screen nil | [spawn_players()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_players) | Spawns the players with inventory at `state.level_gen.spawn_x/y`. Also shop and kali background and probably other stuff for some stupid reason. -nil | [spawn_effects()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_effects) | Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. +nil | [spawn_effects()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_effects) | Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. Spawns beg and handles it's quest flags string | [get_level_file()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_level_file) | Returns: The .lvl file to load (e.g. dwelling = dwellingarea.lvl except when level == 4 (cavebossarea.lvl)) int | [get_theme_id()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_theme_id) | Returns: [THEME](#THEME), or subtheme in CO int | [get_base_id()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_base_id) | Returns: [THEME](#THEME), or logical base [THEME](#THEME) for special levels (Abzu->Tide Pool etc) @@ -3451,8 +3451,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_spawn_traps(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_spawn_traps) | Hooks after the virtual function.
The callback signature is `nil spawn_traps(ThemeInfo self)`
Virtual function docs:
Spawns theme specific random traps, pushblocks and critters. Sets special exit doors. [CallbackId](#Aliases) | [set_pre_post_process_entities(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_post_process_entities) | Hooks before the virtual function.
The callback signature is `bool post_process_entities(ThemeInfo self)`
Virtual function docs:
Fixes textures on pleasure palace ladders, adds some decorations [CallbackId](#Aliases) | [set_post_post_process_entities(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_post_process_entities) | Hooks after the virtual function.
The callback signature is `nil post_process_entities(ThemeInfo self)`
Virtual function docs:
Fixes textures on pleasure palace ladders, adds some decorations -[CallbackId](#Aliases) | [set_pre_spawn_procedural(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_spawn_procedural) | Hooks before the virtual function.
The callback signature is `bool spawn_procedural(ThemeInfo self)`
Virtual function docs:
Adds legs under platforms, random pots, goldbars, monsters, compass indicator, random shadows... -[CallbackId](#Aliases) | [set_post_spawn_procedural(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_spawn_procedural) | Hooks after the virtual function.
The callback signature is `nil spawn_procedural(ThemeInfo self)`
Virtual function docs:
Adds legs under platforms, random pots, goldbars, monsters, compass indicator, random shadows... +[CallbackId](#Aliases) | [set_pre_spawn_procedural(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_spawn_procedural) | Hooks before the virtual function.
The callback signature is `bool spawn_procedural(ThemeInfo self)`
Virtual function docs:
Adds legs under platforms, random pots, goldbars, monsters, compass indicator, initialises quests, random shadows... +[CallbackId](#Aliases) | [set_post_spawn_procedural(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_spawn_procedural) | Hooks after the virtual function.
The callback signature is `nil spawn_procedural(ThemeInfo self)`
Virtual function docs:
Adds legs under platforms, random pots, goldbars, monsters, compass indicator, initialises quests, random shadows... [CallbackId](#Aliases) | [set_pre_spawn_background(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_spawn_background) | Hooks before the virtual function.
The callback signature is `bool spawn_background(ThemeInfo self)`
Virtual function docs:
Adds the main level background , e.g. CO stars / Duat moon / Plain backwall for other themes [CallbackId](#Aliases) | [set_post_spawn_background(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_spawn_background) | Hooks after the virtual function.
The callback signature is `nil spawn_background(ThemeInfo self)`
Virtual function docs:
Adds the main level background , e.g. CO stars / Duat moon / Plain backwall for other themes [CallbackId](#Aliases) | [set_pre_spawn_lights(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_spawn_lights) | Hooks before the virtual function.
The callback signature is `bool spawn_lights(ThemeInfo self)`
Virtual function docs:
Adds room lights to udjat chest room or black market @@ -3463,8 +3463,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_post_transition(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_post_transition) | Hooks after the virtual function.
The callback signature is `nil post_transition(ThemeInfo self)`
Virtual function docs:
Handles loading the next level screen from a transition screen [CallbackId](#Aliases) | [set_pre_spawn_players(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_spawn_players) | Hooks before the virtual function.
The callback signature is `bool spawn_players(ThemeInfo self)`
Virtual function docs:
Spawns the players with inventory at `state.level_gen.spawn_x/y`. Also shop and kali background and probably other stuff for some stupid reason. [CallbackId](#Aliases) | [set_post_spawn_players(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_spawn_players) | Hooks after the virtual function.
The callback signature is `nil spawn_players(ThemeInfo self)`
Virtual function docs:
Spawns the players with inventory at `state.level_gen.spawn_x/y`. Also shop and kali background and probably other stuff for some stupid reason. -[CallbackId](#Aliases) | [set_pre_spawn_effects(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_spawn_effects) | Hooks before the virtual function.
The callback signature is `bool spawn_effects(ThemeInfo self)`
Virtual function docs:
Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. -[CallbackId](#Aliases) | [set_post_spawn_effects(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_spawn_effects) | Hooks after the virtual function.
The callback signature is `nil spawn_effects(ThemeInfo self)`
Virtual function docs:
Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. +[CallbackId](#Aliases) | [set_pre_spawn_effects(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_spawn_effects) | Hooks before the virtual function.
The callback signature is `bool spawn_effects(ThemeInfo self)`
Virtual function docs:
Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. Spawns beg and handles it's quest flags +[CallbackId](#Aliases) | [set_post_spawn_effects(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_spawn_effects) | Hooks after the virtual function.
The callback signature is `nil spawn_effects(ThemeInfo self)`
Virtual function docs:
Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. Spawns beg and handles it's quest flags [CallbackId](#Aliases) | [set_pre_theme_id(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_theme_id) | Hooks before the virtual function.
The callback signature is `optional theme_id(ThemeInfo self)` [CallbackId](#Aliases) | [set_post_theme_id(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_theme_id) | Hooks after the virtual function.
The callback signature is `nil theme_id(ThemeInfo self)` [CallbackId](#Aliases) | [set_pre_base_id(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_base_id) | Hooks before the virtual function.
The callback signature is `optional base_id(ThemeInfo self)` diff --git a/src/game_api/level_api.hpp b/src/game_api/level_api.hpp index 4735c1b44..e8b745f68 100644 --- a/src/game_api/level_api.hpp +++ b/src/game_api/level_api.hpp @@ -313,7 +313,7 @@ class ThemeInfo /// Fixes textures on pleasure palace ladders, adds some decorations virtual void post_process_entities() = 0; - /// Adds legs under platforms, random pots, goldbars, monsters, compass indicator, random shadows... + /// Adds legs under platforms, random pots, goldbars, monsters, compass indicator, initialises quests, random shadows... virtual void spawn_procedural() = 0; /// Adds the main level background , e.g. CO stars / Duat moon / Plain backwall for other themes @@ -331,7 +331,7 @@ class ThemeInfo /// Spawns the players with inventory at `state.level_gen.spawn_x/y`. Also shop and kali background and probably other stuff for some stupid reason. virtual void spawn_players() = 0; - /// Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. + /// Sets the camera bounds and position. Spawns jelly and orbs and the flag in coop. Sets timers/conditions for more jellies and ghosts. Enables the special fog/ember/ice etc particle effects. Spawns beg and handles it's quest flags virtual void spawn_effects() = 0; /// Returns: The .lvl file to load (e.g. dwelling = dwellingarea.lvl except when level == 4 (cavebossarea.lvl)) From 79dcb169f0b23e761d6ba25f85dad26974e0e5b3 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sat, 7 Dec 2024 18:13:40 +0100 Subject: [PATCH 17/21] typos and YellowCape base --- src/game_api/entities_monsters.hpp | 2 +- src/game_api/entities_mounts.hpp | 2 +- src/game_api/script/usertypes/entities_items_lua.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game_api/entities_monsters.hpp b/src/game_api/entities_monsters.hpp index 2e4eaeddd..edb6a9d76 100644 --- a/src/game_api/entities_monsters.hpp +++ b/src/game_api/entities_monsters.hpp @@ -378,7 +378,7 @@ class Lavamander : public Monster uint16_t jump_pause_timer; // jump pause when cool; runs continuously when hot uint8_t lava_detection_timer; bool is_hot; - /// 0 - didn't saw player, 1 - saw player, 2 - spited lava; probably used so he won't spit imminently after seeing the player + /// 0 - didn't see player, 1 - saw player, 2 - spitted lava; probably used so he won't spit imminently after seeing the player uint8_t player_detect_state; uint8_t padding2; }; diff --git a/src/game_api/entities_mounts.hpp b/src/game_api/entities_mounts.hpp index e200e99c3..3bf06631c 100644 --- a/src/game_api/entities_mounts.hpp +++ b/src/game_api/entities_mounts.hpp @@ -19,7 +19,7 @@ class Mount : public PowerupCapable bool tamed; uint16_t walk_pause_timer; // alternates between walking and pausing every time it reaches zero uint8_t unknown9a; - bool double_jumping; // used to play different animation for the double jump then the standard jump, is true for less then a frame + bool double_jumping; // used to play different animation for the double jump then the standard jump, is true for less than a frame uint8_t taming_timer; // when 0 it's tame uint8_t padding2; diff --git a/src/game_api/script/usertypes/entities_items_lua.cpp b/src/game_api/script/usertypes/entities_items_lua.cpp index 29d4230c7..c086e74a5 100644 --- a/src/game_api/script/usertypes/entities_items_lua.cpp +++ b/src/game_api/script/usertypes/entities_items_lua.cpp @@ -989,7 +989,7 @@ void register_usertypes(sol::state& lua) "sound", &YellowCape::sound, sol::base_classes, - sol::bases()); + sol::bases()); lua.new_usertype( "Teleporter", From 380de08cfb48e57dae3118545bbb4615e2c02328 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sun, 8 Dec 2024 22:40:16 +0100 Subject: [PATCH 18/21] rename `pickup` to `give_powerup` and expose it, fix comments for vtable function that have different name for hook vs function itself, some comments here and there --- docs/game_data/spel2.lua | 50 ++++++++++-------- docs/parse_source.py | 8 +-- docs/src/includes/_enums.md | 1 + docs/src/includes/_types.md | 52 +++++++++++-------- src/game_api/entities_chars.hpp | 2 +- src/game_api/entities_items.hpp | 2 +- src/game_api/movable.hpp | 10 ++-- .../script/usertypes/entities_items_lua.cpp | 2 + src/game_api/script/usertypes/vtables_lua.cpp | 8 ++- 9 files changed, 79 insertions(+), 56 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index d1a366caf..e870263a3 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -2617,12 +2617,12 @@ function PRNG:random(min, max) end ---@field set_post_walked_off fun(self, fun: fun(self: Entity, walker: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil walked_off(Entity self, Entity walker)` ---@field set_pre_ledge_grab fun(self, fun: fun(self: Entity, who: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool ledge_grab(Entity self, Entity who)` ---@field set_post_ledge_grab fun(self, fun: fun(self: Entity, who: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil ledge_grab(Entity self, Entity who)` - ---@field set_pre_stood_on fun(self, fun: fun(self: Entity, Vec2: Entity entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool stood_on(Entity self, Entity entity Vec2)` - ---@field set_post_stood_on fun(self, fun: fun(self: Entity, Vec2: Entity entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil stood_on(Entity self, Entity entity Vec2)` + ---@field set_pre_stood_on fun(self, fun: fun(self: Entity, entity: Entity, Vec2: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool stood_on(Entity self, Entity entity, Vec2)` + ---@field set_post_stood_on fun(self, fun: fun(self: Entity, entity: Entity, Vec2: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil stood_on(Entity self, Entity entity, Vec2)` ---@field set_pre_liberate_from_shop fun(self, fun: fun(self: Entity, clear_parrent: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool liberate_from_shop(Entity self, boolean clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought ---@field set_post_liberate_from_shop fun(self, fun: fun(self: Entity, clear_parrent: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil liberate_from_shop(Entity self, boolean clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought - ---@field set_pre_init fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool init(Entity self)` - ---@field set_post_init fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil init(Entity self)` + ---@field set_pre_init fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool init(Entity self)`
Virtual function docs:
Applies changes made in `entity.type` + ---@field set_post_init fun(self, fun: fun(self: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil init(Entity self)`
Virtual function docs:
Applies changes made in `entity.type` local Entity = nil ---@param hitbox AABB ---@return boolean @@ -2714,7 +2714,7 @@ function Entity:destroy_recursive() end ---@field can_be_picked_up_by fun(self, entity_picking_up: Entity, boolean: ): boolean ---@field can_break_block fun(self, horizontal: boolean, block: Entity): boolean ---@field break_block fun(self, camera_shake: boolean, block: Entity): nil - ---@field damage fun(self, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean @Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer + ---@field damage fun(self, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean @Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like: if pot was thrown into entity, should that pot break after hit), false if the event should be ignored by damage_dealer ---@field get_all_behaviors fun(self): integer[] @Get all available behavior ids ---@field set_behavior fun(self, behavior_id: integer): boolean @Set behavior, this is more than just state as it's an active function, for example climbing ladder is a behavior and it doesn't actually need ladder/rope entity
Returns false if entity doesn't have this behavior id ---@field get_behavior fun(self): integer @Get the current behavior id @@ -2754,8 +2754,8 @@ function Entity:destroy_recursive() end ---@field set_post_attack fun(self, fun: fun(self: Movable, victim: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil attack(Movable self, Entity victim)`
Virtual function docs:
Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) ---@field set_pre_thrown_into fun(self, fun: fun(self: Movable, victim: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional thrown_into(Movable self, Entity victim)`
Virtual function docs:
Same as above, but for being thrown into something and potentially dealing damage that way ---@field set_post_thrown_into fun(self, fun: fun(self: Movable, victim: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil thrown_into(Movable self, Entity victim)`
Virtual function docs:
Same as above, but for being thrown into something and potentially dealing damage that way - ---@field set_pre_damage fun(self, fun: fun(self: Movable, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional damage(Movable self, Entity damage_dealer, integer damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, integer unknown_damage_phase, integer stun_amount, integer iframes, boolean unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer - ---@field set_post_damage fun(self, fun: fun(self: Movable, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, integer damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, integer unknown_damage_phase, integer stun_amount, integer iframes, boolean unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer + ---@field set_pre_damage fun(self, fun: fun(self: Movable, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional damage(Movable self, Entity damage_dealer, integer damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, integer unknown_damage_phase, integer stun_amount, integer iframes, boolean unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like: if pot was thrown into entity, should that pot break after hit), false if the event should be ignored by damage_dealer + ---@field set_post_damage fun(self, fun: fun(self: Movable, damage_dealer: Entity, damage_amount: integer, damage_flags: DAMAGE_TYPE, velocity: Vec2, unknown_damage_phase: integer, stun_amount: integer, iframes: integer, unknown_is_final: boolean): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, integer damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, integer unknown_damage_phase, integer stun_amount, integer iframes, boolean unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like: if pot was thrown into entity, should that pot break after hit), false if the event should be ignored by damage_dealer ---@field set_pre_on_hit fun(self, fun: fun(self: Movable, damage_dealer: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. ---@field set_post_on_hit fun(self, fun: fun(self: Movable, damage_dealer: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. ---@field set_pre_get_damage_sound fun(self, fun: fun(self: Movable, damage: DAMAGE_TYPE): SOUNDID?): CallbackId @Hooks before the virtual function.
The callback signature is `optional get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence @@ -2780,8 +2780,8 @@ function Entity:destroy_recursive() end ---@field set_post_stomped_by fun(self, fun: fun(self: Movable, stomper: Entity): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil stomped_by(Movable self, Entity stomper)` ---@field set_pre_thrown_by fun(self, fun: fun(self: Movable, thrower: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool thrown_by(Movable self, Entity thrower)` ---@field set_post_thrown_by fun(self, fun: fun(self: Movable, thrower: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil thrown_by(Movable self, Entity thrower)` - ---@field set_pre_cloned_to fun(self, fun: fun(self: Movable, some_entity_uid: Entity clone integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool cloned_to(Movable self, Entity clone integer some_entity_uid)` - ---@field set_post_cloned_to fun(self, fun: fun(self: Movable, some_entity_uid: Entity clone integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil cloned_to(Movable self, Entity clone integer some_entity_uid)` + ---@field set_pre_cloned_to fun(self, fun: fun(self: Movable, clone: Entity, some_entity_uid: integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool cloned_to(Movable self, Entity clone, integer some_entity_uid)`
Virtual function docs:
Entities must be of the same type! + ---@field set_post_cloned_to fun(self, fun: fun(self: Movable, clone: Entity, some_entity_uid: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil cloned_to(Movable self, Entity clone, integer some_entity_uid)`
Virtual function docs:
Entities must be of the same type! ---@field set_pre_pick_up fun(self, fun: fun(self: Movable, entity_to_pick_up: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool pick_up(Movable self, Entity entity_to_pick_up)` ---@field set_post_pick_up fun(self, fun: fun(self: Movable, entity_to_pick_up: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil pick_up(Movable self, Entity entity_to_pick_up)` ---@field set_pre_can_be_picked_up_by fun(self, fun: fun(self: Movable, entity_picking_up: Entity, boolean: ): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional can_be_picked_up_by(Movable self, Entity entity_picking_up, boolean)` @@ -2798,14 +2798,14 @@ function Entity:destroy_recursive() end ---@field set_post_initialize fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil initialize(Movable self)` ---@field set_pre_process_input fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool process_input(Movable self)` ---@field set_post_process_input fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil process_input(Movable self)` - ---@field set_pre_picked_up fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool picked_up(Movable self)` - ---@field set_post_picked_up fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil picked_up(Movable self)` - ---@field set_pre_release fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool release(Movable self)` - ---@field set_post_release fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil release(Movable self)` + ---@field set_pre_picked_up fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool picked_up(Movable self)`
Virtual function docs:
Called for entity that just has been picked up + ---@field set_post_picked_up fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil picked_up(Movable self)`
Virtual function docs:
Called for entity that just has been picked up + ---@field set_pre_release fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool release(Movable self)`
Virtual function docs:
Called for entity that just has been thrown/dropped + ---@field set_post_release fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil release(Movable self)`
Virtual function docs:
Called for entity that just has been thrown/dropped ---@field set_pre_generate_fall_poof_particles fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool generate_fall_poof_particles(Movable self)` ---@field set_post_generate_fall_poof_particles fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil generate_fall_poof_particles(Movable self)` - ---@field set_pre_fall fun(self, fun: fun(self: Movable, number: number): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool fall(Movable self, number number)` - ---@field set_post_fall fun(self, fun: fun(self: Movable, number: number): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil fall(Movable self, number number)` + ---@field set_pre_fall fun(self, fun: fun(self: Movable, number: number): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool fall(Movable self, number number)`
Virtual function docs:
Applies gravity to entity. Disable to float like on hoverpack. + ---@field set_post_fall fun(self, fun: fun(self: Movable, number: number): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil fall(Movable self, number number)`
Virtual function docs:
Applies gravity to entity. Disable to float like on hoverpack. ---@field set_pre_apply_friction fun(self, fun: fun(self: Movable, number: , vertical: boolean, number: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool apply_friction(Movable self, number, boolean vertical, number)` ---@field set_post_apply_friction fun(self, fun: fun(self: Movable, number: , vertical: boolean, number: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil apply_friction(Movable self, number, boolean vertical, number)` ---@field set_pre_can_break_block fun(self, fun: fun(self: Movable, horizontal: boolean, block: Entity): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional can_break_block(Movable self, boolean horizontal, Entity block)` @@ -2849,8 +2849,8 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. - ---@field set_pre_blood_collision fun(self, fun: fun(self: PowerupCapable): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional blood_collision(PowerupCapable self)` - ---@field set_post_blood_collision fun(self, fun: fun(self: PowerupCapable): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil blood_collision(PowerupCapable self)` + ---@field set_pre_blood_collision fun(self, fun: fun(self: PowerupCapable): boolean?): CallbackId @Hooks before the virtual function.
The callback signature is `optional blood_collision(PowerupCapable self)`
Virtual function docs:
only triggers when entity has kapala + ---@field set_post_blood_collision fun(self, fun: fun(self: PowerupCapable): boolean?): CallbackId @Hooks after the virtual function.
The callback signature is `nil blood_collision(PowerupCapable self)`
Virtual function docs:
only triggers when entity has kapala ---@class Inventory ---@field money integer @Sum of the money collected in current level @@ -3385,7 +3385,7 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field jump_pause_timer integer ---@field lava_detection_timer integer ---@field is_hot boolean - ---@field player_detect_state integer @0 - didn't saw player, 1 - saw player, 2 - spited lava; probably used so he won't spit imminently after seeing the player + ---@field player_detect_state integer @0 - didn't see player, 1 - saw player, 2 - spitted lava; probably used so he won't spit imminently after seeing the player ---@class Firebug : Monster ---@field sound SoundMeta @@ -4198,6 +4198,12 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@class RollingItem : Purchasable ---@field roll_speed number + ---@field give_powerup fun(self, who: Entity, boolean: ): nil @Skip this function for item to be unpickable + ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. + ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. + ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. + ---@field set_pre_give_powerup fun(self, fun: fun(self: RollingItem, who: Entity, boolean: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool give_powerup(RollingItem self, Entity who, boolean)`
Virtual function docs:
Skip this function for item to be unpickable + ---@field set_post_give_powerup fun(self, fun: fun(self: RollingItem, who: Entity, boolean: ): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil give_powerup(RollingItem self, Entity who, boolean)`
Virtual function docs:
Skip this function for item to be unpickable ---@class PlayerBag : Movable ---@field bombs integer @@ -4207,10 +4213,10 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. - ---@field set_pre_putting_on fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool putting_on(Powerup self, PowerupCapable who)` - ---@field set_post_putting_on fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil putting_on(Powerup self, PowerupCapable who)` - ---@field set_pre_putting_off fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool putting_off(Powerup self, PowerupCapable who)` - ---@field set_post_putting_off fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil putting_off(Powerup self, PowerupCapable who)` + ---@field set_pre_putting_on fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool putting_on(Powerup self, PowerupCapable who)`
Virtual function docs:
only for backpacks + ---@field set_post_putting_on fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil putting_on(Powerup self, PowerupCapable who)`
Virtual function docs:
only for backpacks + ---@field set_pre_putting_off fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool putting_off(Powerup self, PowerupCapable who)`
Virtual function docs:
only for backpacks + ---@field set_post_putting_off fun(self, fun: fun(self: Powerup, who: PowerupCapable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil putting_off(Powerup self, PowerupCapable who)`
Virtual function docs:
only for backpacks ---@class KapalaPowerup : Powerup ---@field amount_of_blood integer diff --git a/docs/parse_source.py b/docs/parse_source.py index 68fd4375e..81985c1ef 100644 --- a/docs/parse_source.py +++ b/docs/parse_source.py @@ -630,7 +630,6 @@ def run_parse(): for item in classes: if item["name"] != func_ref.group(1): continue - # TODO: pretty sure if the actual virtual function name is different then the one in VTableEntry there won't be comment in callback signature func_name = func_ref.group(2) # if it throws error at `item["member_funs"][func_name]` then the virtual defined using MemFun was not found in the parsed class/struct code if ( @@ -645,8 +644,8 @@ def run_parse(): "index": index, "ret": func["return"], "args": [t for t in func["param"].split(",")], - # "ref": func_name.group(2), "binds": binds, + "ref": func_name, } else: signature = re.search(r"([_a-zA-Z][\w]*.*)\((.*)\)", signature) @@ -920,11 +919,12 @@ def run_parse(): for entry in vtable["entries"].values(): entry_name = entry["name"] + func_name = entry["ref"] if "ref" in entry else entry["name"] pre_signature = None post_signature = None cpp_comment = [] - if entry_name in underlying_cpp_type["member_funs"]: - for fun in underlying_cpp_type["member_funs"][entry_name]: + if func_name in underlying_cpp_type["member_funs"]: + for fun in underlying_cpp_type["member_funs"][func_name]: ret = replace_fun(fun["return"]) ret = f"optional<{ret}>" if ret else "bool" ret = ret if entry_name != "dtor" else "nil" diff --git a/docs/src/includes/_enums.md b/docs/src/includes/_enums.md index 5161ebe57..74ffffd4a 100644 --- a/docs/src/includes/_enums.md +++ b/docs/src/includes/_enums.md @@ -308,6 +308,7 @@ Name | Data | Description [ACQUIRE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.ACQUIRE) | 93 | [TRIGGER_EXPLOSION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.TRIGGER_EXPLOSION) | 94 | [SPAWN_PROJECTILE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.SPAWN_PROJECTILE) | 93 | +[GIVE_POWERUP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GIVE_POWERUP) | 93 | ## ENT_FLAG diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 61ba1a419..796f23a52 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -4332,12 +4332,12 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_walked_off(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_walked_off) | Hooks after the virtual function.
The callback signature is `nil walked_off(Entity self, Entity walker)` [CallbackId](#Aliases) | [set_pre_ledge_grab(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_ledge_grab) | Hooks before the virtual function.
The callback signature is `bool ledge_grab(Entity self, Entity who)` [CallbackId](#Aliases) | [set_post_ledge_grab(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_ledge_grab) | Hooks after the virtual function.
The callback signature is `nil ledge_grab(Entity self, Entity who)` -[CallbackId](#Aliases) | [set_pre_stood_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stood_on) | Hooks before the virtual function.
The callback signature is `bool stood_on(Entity self, Entity entity Vec2)` -[CallbackId](#Aliases) | [set_post_stood_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stood_on) | Hooks after the virtual function.
The callback signature is `nil stood_on(Entity self, Entity entity Vec2)` +[CallbackId](#Aliases) | [set_pre_stood_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stood_on) | Hooks before the virtual function.
The callback signature is `bool stood_on(Entity self, Entity entity, Vec2)` +[CallbackId](#Aliases) | [set_post_stood_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stood_on) | Hooks after the virtual function.
The callback signature is `nil stood_on(Entity self, Entity entity, Vec2)` [CallbackId](#Aliases) | [set_pre_liberate_from_shop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_liberate_from_shop) | Hooks before the virtual function.
The callback signature is `bool liberate_from_shop(Entity self, bool clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought [CallbackId](#Aliases) | [set_post_liberate_from_shop(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_liberate_from_shop) | Hooks after the virtual function.
The callback signature is `nil liberate_from_shop(Entity self, bool clear_parrent)`
Virtual function docs:
`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought -[CallbackId](#Aliases) | [set_pre_init(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_init) | Hooks before the virtual function.
The callback signature is `bool init(Entity self)` -[CallbackId](#Aliases) | [set_post_init(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_init) | Hooks after the virtual function.
The callback signature is `nil init(Entity self)` +[CallbackId](#Aliases) | [set_pre_init(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_init) | Hooks before the virtual function.
The callback signature is `bool init(Entity self)`
Virtual function docs:
Applies changes made in `entity.type` +[CallbackId](#Aliases) | [set_post_init(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_init) | Hooks after the virtual function.
The callback signature is `nil init(Entity self)`
Virtual function docs:
Applies changes made in `entity.type` ### IceSlidingSound @@ -5232,7 +5232,7 @@ int | [shoot_lava_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua& int | [jump_pause_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=jump_pause_timer) | int | [lava_detection_timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=lava_detection_timer) | bool | [is_hot](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_hot) | -int | [player_detect_state](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_detect_state) | 0 - didn't saw player, 1 - saw player, 2 - spited lava; probably used so he won't spit imminently after seeing the player +int | [player_detect_state](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=player_detect_state) | 0 - didn't see player, 1 - saw player, 2 - spitted lava; probably used so he won't spit imminently after seeing the player ### Leprechaun @@ -5517,8 +5517,8 @@ int | [worn_backitem()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q [CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. [CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. -[CallbackId](#Aliases) | [set_pre_blood_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_blood_collision) | Hooks before the virtual function.
The callback signature is `optional blood_collision(PowerupCapable self)` -[CallbackId](#Aliases) | [set_post_blood_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_blood_collision) | Hooks after the virtual function.
The callback signature is `nil blood_collision(PowerupCapable self)` +[CallbackId](#Aliases) | [set_pre_blood_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_blood_collision) | Hooks before the virtual function.
The callback signature is `optional blood_collision(PowerupCapable self)`
Virtual function docs:
only triggers when entity has kapala +[CallbackId](#Aliases) | [set_post_blood_collision(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_blood_collision) | Hooks after the virtual function.
The callback signature is `nil blood_collision(PowerupCapable self)`
Virtual function docs:
only triggers when entity has kapala ### ProtoShopkeeper @@ -6987,7 +6987,7 @@ bool | [is_powerup_capable()](https://github.com/spelunky-fyi/overlunky/search?l bool | [can_be_picked_up_by(Entity entity_picking_up, bool)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=can_be_picked_up_by) | bool | [can_break_block(bool horizontal, Entity block)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=can_break_block) | nil | [break_block(bool camera_shake, Entity block)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=break_block) | -bool | [damage(Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=damage) | Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer +bool | [damage(Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=damage) | Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like: if pot was thrown into entity, should that pot break after hit), false if the event should be ignored by damage_dealer vector<int> | [get_all_behaviors()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_all_behaviors) | Get all available behavior ids bool | [set_behavior(int behavior_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_behavior) | Set behavior, this is more than just state as it's an active function, for example climbing ladder is a behavior and it doesn't actually need ladder/rope entity
Returns false if entity doesn't have this behavior id int | [get_behavior()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_behavior) | Get the current behavior id @@ -7030,8 +7030,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_attack(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_attack) | Hooks after the virtual function.
The callback signature is `nil attack(Movable self, Entity victim)`
Virtual function docs:
Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) [CallbackId](#Aliases) | [set_pre_thrown_into(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_thrown_into) | Hooks before the virtual function.
The callback signature is `optional thrown_into(Movable self, Entity victim)`
Virtual function docs:
Same as above, but for being thrown into something and potentially dealing damage that way [CallbackId](#Aliases) | [set_post_thrown_into(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_thrown_into) | Hooks after the virtual function.
The callback signature is `nil thrown_into(Movable self, Entity victim)`
Virtual function docs:
Same as above, but for being thrown into something and potentially dealing damage that way -[CallbackId](#Aliases) | [set_pre_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_damage) | Hooks before the virtual function.
The callback signature is `optional damage(Movable self, Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer -[CallbackId](#Aliases) | [set_post_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_damage) | Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer +[CallbackId](#Aliases) | [set_pre_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_damage) | Hooks before the virtual function.
The callback signature is `optional damage(Movable self, Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like: if pot was thrown into entity, should that pot break after hit), false if the event should be ignored by damage_dealer +[CallbackId](#Aliases) | [set_post_damage(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_damage) | Hooks after the virtual function.
The callback signature is `nil damage(Movable self, Entity damage_dealer, int damage_amount, DAMAGE_TYPE damage_flags, Vec2 velocity, int unknown_damage_phase, int stun_amount, int iframes, bool unknown_is_final)`
Virtual function docs:
Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil.
Returns: true if entity was affected (for stuff like: if pot was thrown into entity, should that pot break after hit), false if the event should be ignored by damage_dealer [CallbackId](#Aliases) | [set_pre_on_hit(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_on_hit) | Hooks before the virtual function.
The callback signature is `bool on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. [CallbackId](#Aliases) | [set_post_on_hit(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_on_hit) | Hooks after the virtual function.
The callback signature is `nil on_hit(Movable self, Entity damage_dealer)`
Virtual function docs:
Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. [CallbackId](#Aliases) | [set_pre_get_damage_sound(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_get_damage_sound) | Hooks before the virtual function.
The callback signature is `optional get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence @@ -7056,8 +7056,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_stomped_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stomped_by) | Hooks after the virtual function.
The callback signature is `nil stomped_by(Movable self, Entity stomper)` [CallbackId](#Aliases) | [set_pre_thrown_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_thrown_by) | Hooks before the virtual function.
The callback signature is `bool thrown_by(Movable self, Entity thrower)` [CallbackId](#Aliases) | [set_post_thrown_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_thrown_by) | Hooks after the virtual function.
The callback signature is `nil thrown_by(Movable self, Entity thrower)` -[CallbackId](#Aliases) | [set_pre_cloned_to(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_cloned_to) | Hooks before the virtual function.
The callback signature is `bool cloned_to(Movable self, Entity clone int some_entity_uid)` -[CallbackId](#Aliases) | [set_post_cloned_to(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_cloned_to) | Hooks after the virtual function.
The callback signature is `nil cloned_to(Movable self, Entity clone int some_entity_uid)` +[CallbackId](#Aliases) | [set_pre_cloned_to(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_cloned_to) | Hooks before the virtual function.
The callback signature is `bool cloned_to(Movable self, Entity clone, int some_entity_uid)`
Virtual function docs:
Entities must be of the same type! +[CallbackId](#Aliases) | [set_post_cloned_to(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_cloned_to) | Hooks after the virtual function.
The callback signature is `nil cloned_to(Movable self, Entity clone, int some_entity_uid)`
Virtual function docs:
Entities must be of the same type! [CallbackId](#Aliases) | [set_pre_pick_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_pick_up) | Hooks before the virtual function.
The callback signature is `bool pick_up(Movable self, Entity entity_to_pick_up)` [CallbackId](#Aliases) | [set_post_pick_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_pick_up) | Hooks after the virtual function.
The callback signature is `nil pick_up(Movable self, Entity entity_to_pick_up)` [CallbackId](#Aliases) | [set_pre_can_be_picked_up_by(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_can_be_picked_up_by) | Hooks before the virtual function.
The callback signature is `optional can_be_picked_up_by(Movable self, Entity entity_picking_up, bool)` @@ -7074,14 +7074,14 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_initialize(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_initialize) | Hooks after the virtual function.
The callback signature is `nil initialize(Movable self)` [CallbackId](#Aliases) | [set_pre_process_input(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_process_input) | Hooks before the virtual function.
The callback signature is `bool process_input(Movable self)` [CallbackId](#Aliases) | [set_post_process_input(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_process_input) | Hooks after the virtual function.
The callback signature is `nil process_input(Movable self)` -[CallbackId](#Aliases) | [set_pre_picked_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_picked_up) | Hooks before the virtual function.
The callback signature is `bool picked_up(Movable self)` -[CallbackId](#Aliases) | [set_post_picked_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_picked_up) | Hooks after the virtual function.
The callback signature is `nil picked_up(Movable self)` -[CallbackId](#Aliases) | [set_pre_release(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_release) | Hooks before the virtual function.
The callback signature is `bool release(Movable self)` -[CallbackId](#Aliases) | [set_post_release(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_release) | Hooks after the virtual function.
The callback signature is `nil release(Movable self)` +[CallbackId](#Aliases) | [set_pre_picked_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_picked_up) | Hooks before the virtual function.
The callback signature is `bool picked_up(Movable self)`
Virtual function docs:
Called for entity that just has been picked up +[CallbackId](#Aliases) | [set_post_picked_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_picked_up) | Hooks after the virtual function.
The callback signature is `nil picked_up(Movable self)`
Virtual function docs:
Called for entity that just has been picked up +[CallbackId](#Aliases) | [set_pre_release(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_release) | Hooks before the virtual function.
The callback signature is `bool release(Movable self)`
Virtual function docs:
Called for entity that just has been thrown/dropped +[CallbackId](#Aliases) | [set_post_release(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_release) | Hooks after the virtual function.
The callback signature is `nil release(Movable self)`
Virtual function docs:
Called for entity that just has been thrown/dropped [CallbackId](#Aliases) | [set_pre_generate_fall_poof_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_generate_fall_poof_particles) | Hooks before the virtual function.
The callback signature is `bool generate_fall_poof_particles(Movable self)` [CallbackId](#Aliases) | [set_post_generate_fall_poof_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_generate_fall_poof_particles) | Hooks after the virtual function.
The callback signature is `nil generate_fall_poof_particles(Movable self)` -[CallbackId](#Aliases) | [set_pre_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_fall) | Hooks before the virtual function.
The callback signature is `bool fall(Movable self, float float)` -[CallbackId](#Aliases) | [set_post_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_fall) | Hooks after the virtual function.
The callback signature is `nil fall(Movable self, float float)` +[CallbackId](#Aliases) | [set_pre_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_fall) | Hooks before the virtual function.
The callback signature is `bool fall(Movable self, float float)`
Virtual function docs:
Applies gravity to entity. Disable to float like on hoverpack. +[CallbackId](#Aliases) | [set_post_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_fall) | Hooks after the virtual function.
The callback signature is `nil fall(Movable self, float float)`
Virtual function docs:
Applies gravity to entity. Disable to float like on hoverpack. [CallbackId](#Aliases) | [set_pre_apply_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_apply_friction) | Hooks before the virtual function.
The callback signature is `bool apply_friction(Movable self, float, bool vertical, float)` [CallbackId](#Aliases) | [set_post_apply_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_apply_friction) | Hooks after the virtual function.
The callback signature is `nil apply_friction(Movable self, float, bool vertical, float)` [CallbackId](#Aliases) | [set_pre_can_break_block(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_can_break_block) | Hooks before the virtual function.
The callback signature is `optional can_break_block(Movable self, bool horizontal, Entity block)` @@ -7227,10 +7227,10 @@ Type | Name | Description [CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. [CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. -[CallbackId](#Aliases) | [set_pre_putting_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_putting_on) | Hooks before the virtual function.
The callback signature is `bool putting_on(Powerup self, PowerupCapable who)` -[CallbackId](#Aliases) | [set_post_putting_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_putting_on) | Hooks after the virtual function.
The callback signature is `nil putting_on(Powerup self, PowerupCapable who)` -[CallbackId](#Aliases) | [set_pre_putting_off(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_putting_off) | Hooks before the virtual function.
The callback signature is `bool putting_off(Powerup self, PowerupCapable who)` -[CallbackId](#Aliases) | [set_post_putting_off(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_putting_off) | Hooks after the virtual function.
The callback signature is `nil putting_off(Powerup self, PowerupCapable who)` +[CallbackId](#Aliases) | [set_pre_putting_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_putting_on) | Hooks before the virtual function.
The callback signature is `bool putting_on(Powerup self, PowerupCapable who)`
Virtual function docs:
only for backpacks +[CallbackId](#Aliases) | [set_post_putting_on(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_putting_on) | Hooks after the virtual function.
The callback signature is `nil putting_on(Powerup self, PowerupCapable who)`
Virtual function docs:
only for backpacks +[CallbackId](#Aliases) | [set_pre_putting_off(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_putting_off) | Hooks before the virtual function.
The callback signature is `bool putting_off(Powerup self, PowerupCapable who)`
Virtual function docs:
only for backpacks +[CallbackId](#Aliases) | [set_post_putting_off(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_putting_off) | Hooks after the virtual function.
The callback signature is `nil putting_off(Powerup self, PowerupCapable who)`
Virtual function docs:
only for backpacks ### Present @@ -7313,6 +7313,12 @@ Derived from [Entity](#Entity) [Movable](#Movable) [Purchasable](#Purchasable) Type | Name | Description ---- | ---- | ----------- float | [roll_speed](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=roll_speed) | +nil | [give_powerup(Entity who, bool)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=give_powerup) | Skip this function for item to be unpickable +[CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. +[CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. +nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. +[CallbackId](#Aliases) | [set_pre_give_powerup(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_give_powerup) | Hooks before the virtual function.
The callback signature is `bool give_powerup(RollingItem self, Entity who, bool)`
Virtual function docs:
Skip this function for item to be unpickable +[CallbackId](#Aliases) | [set_post_give_powerup(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_give_powerup) | Hooks after the virtual function.
The callback signature is `nil give_powerup(RollingItem self, Entity who, bool)`
Virtual function docs:
Skip this function for item to be unpickable ### Rubble @@ -7687,7 +7693,7 @@ float | [falling_speed](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q ### YellowCape -Derived from [Entity](#Entity) [Movable](#Movable) [Backpack](#Backpack) [Cape](#Cape) +Derived from [Entity](#Entity) [Movable](#Movable) [Powerup](#Powerup) [Backpack](#Backpack) [Cape](#Cape) Type | Name | Description diff --git a/src/game_api/entities_chars.hpp b/src/game_api/entities_chars.hpp index 9eadf6934..e8940d85b 100644 --- a/src/game_api/entities_chars.hpp +++ b/src/game_api/entities_chars.hpp @@ -93,7 +93,7 @@ class PowerupCapable : public Movable /// Returns the uid of the currently worn backitem, or -1 if wearing nothing int32_t worn_backitem(); - /// only triggers when it has kapala + /// only triggers when entity has kapala virtual bool on_blood_collision() = 0; // called for stunned entities, check bunch of stuff like state, hold entity, standing on entity etc. runs until returned 1 // this is used to clear the last_owner of stunned entity when it is no longed stunned diff --git a/src/game_api/entities_items.hpp b/src/game_api/entities_items.hpp index 2ee033901..7245214ff 100644 --- a/src/game_api/entities_items.hpp +++ b/src/game_api/entities_items.hpp @@ -766,7 +766,7 @@ class RollingItem : public Purchasable float roll_speed; // only positive numbers /// Skip this function for item to be unpickable - virtual void pickup(Entity* who, bool) = 0; + virtual void give_powerup(Entity* who, bool) = 0; }; class PlayerBag : public Movable diff --git a/src/game_api/movable.hpp b/src/game_api/movable.hpp index cec678771..12ecc5332 100644 --- a/src/game_api/movable.hpp +++ b/src/game_api/movable.hpp @@ -156,7 +156,7 @@ class Movable : public Entity virtual bool thrown_into(Entity* victim) = 0; // 47 /// Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil. - /// Returns: true if entity was affected (for stuff like pot that should break after hit etc.), false if the event should be ignored by damage_dealer + /// Returns: true if entity was affected (for stuff like: if pot was thrown into entity, should that pot break after hit), false if the event should be ignored by damage_dealer virtual bool damage(Entity* damage_dealer, int8_t damage_amount, DAMAGE_TYPE damage_flags, Vec2* velocity, uint8_t unknown_damage_phase, uint16_t stun_amount, uint8_t iframes, bool unknown_is_final) = 0; // 48 /// Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. @@ -200,9 +200,11 @@ class Movable : public Entity virtual void v77() = 0; // 77 virtual void process_input() = 0; // 78, more like: handle_movement virtual void post_collision_damage_related() = 0; // 79, used for enemies attacks as well? 3 versions for: eggplant minister, players and the rest - virtual void on_picked_up() = 0; // 80, plays pickup sound depending on the entity mask/type etc. set stun for pets and mounts etc. - virtual void on_release() = 0; // 81, only for hired hands and lava pots - virtual void generate_fall_poof_particles() = 0; // 82, entity.velocityy must be < -0.12 to generate a poof, might do other stuff regarding falling/landing + /// Called for entity that just has been picked up + virtual void on_picked_up() = 0; // 80, plays pickup sound depending on the entity mask/type etc. set stun for pets and mounts etc. + /// Called for entity that just has been thrown/dropped + virtual void on_release() = 0; // 81, only for hired hands and lava pots, the rest just returns + virtual void generate_fall_poof_particles() = 0; // 82, entity.velocityy must be < -0.12 to generate a poof, might do other stuff regarding falling/landing /// Applies gravity to entity. Disable to float like on hoverpack. virtual void handle_fall_logic(float) = 0; // 83, adjusts entity.velocityy when falling virtual void apply_friction(float, bool vertical, float) = 0; // 84, applies entity.type.friction to entity.velocityx, the two floats for characters just multiply the friction, could also be returning the value diff --git a/src/game_api/script/usertypes/entities_items_lua.cpp b/src/game_api/script/usertypes/entities_items_lua.cpp index c086e74a5..045d38c2b 100644 --- a/src/game_api/script/usertypes/entities_items_lua.cpp +++ b/src/game_api/script/usertypes/entities_items_lua.cpp @@ -919,6 +919,8 @@ void register_usertypes(sol::state& lua) "RollingItem", "roll_speed", &RollingItem::roll_speed, + "give_powerup", + &RollingItem::give_powerup, sol::base_classes, sol::bases()); diff --git a/src/game_api/script/usertypes/vtables_lua.cpp b/src/game_api/script/usertypes/vtables_lua.cpp index 87af1ede9..cc7914ace 100644 --- a/src/game_api/script/usertypes/vtables_lua.cpp +++ b/src/game_api/script/usertypes/vtables_lua.cpp @@ -210,11 +210,17 @@ void register_usertypes(sol::state& lua) VTableEntry<"spawn_projectile", 93, MemFun<&OlmecCannon::spawn_projectile>>>; static OlmecCannonVTable olmec_cannon_vtable(lua, lua["OlmecCannon"], "ENTITY_OVERRIDE"); + using RollingItemVTable = HookableVTable< + Entity, + CallbackType::Entity, + EntityVTable, + VTableEntry<"give_powerup", 93, MemFun<&RollingItem::give_powerup>>>; + static RollingItemVTable rolling_item_vtable(lua, lua["RollingItem"], "ENTITY_OVERRIDE"); + // Arrow // poison_arrow // light_up ? // Torch // light_up // get_flame_offset // get_flame_type // Bow // get_arrow_special_offset // Generator // randomize_timer ? - // RollingItem // pickup // SoundMeta // start // kill //update maybe? // CritterSlime + CritterSnail // get_speed // Ghist // on_body_destroyed From 85b89994718bd149ada2a5963afaf6ed9d8427c8 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Thu, 12 Dec 2024 21:10:40 +0100 Subject: [PATCH 19/21] make b3f optional in `set_draw_depth`, manually align some comments in entity and movable --- docs/game_data/spel2.lua | 8 +++---- docs/parse_source.py | 2 +- docs/src/includes/_types.md | 8 +++---- src/game_api/entity.hpp | 21 ++++++---------- src/game_api/movable.hpp | 25 +++++++++----------- src/game_api/script/usertypes/entity_lua.cpp | 7 +++--- 6 files changed, 30 insertions(+), 41 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index e870263a3..4e373567a 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -2534,7 +2534,7 @@ function PRNG:random(min, max) end ---@field topmost fun(self): Entity @Returns the top entity in a chain (overlay) ---@field get_texture fun(self): TEXTURE ---@field set_texture fun(self, texture_id: TEXTURE): boolean @Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one - ---@field set_draw_depth fun(self, draw_depth: integer, b3f: integer): nil + ---@field set_draw_depth fun(self, draw_depth: integer, unknown: integer?): nil ---@field reset_draw_depth fun(self): nil ---@field friction fun(self): number @Friction of this entity, affects it's contact with other entities (how fast it slows down on the floor, how fast it can move but also the other way around for floors/activefloors: how other entities can move on it) ---@field liberate_from_shop fun(self, clear_parrent: boolean): nil @`clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought @@ -2701,7 +2701,7 @@ function Entity:destroy_recursive() end ---@field is_button_held fun(self, button: BUTTON): boolean ---@field is_button_released fun(self, button: BUTTON): boolean ---@field stun fun(self, framecount: integer): nil - ---@field freeze fun(self, framecount: integer, ignore_lava: boolean): nil @Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time + ---@field freeze fun(self, framecount: integer, ignore_lava: boolean): nil @Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check,
if in lava the game will set `frozen_timer` to 0 immediately most of the time ---@field light_on_fire fun(self, time: integer): nil @Does not damage entity ---@field set_cursed fun(self, b: boolean, effect: boolean): nil ---@field drop fun(self): nil @Called when dropping or throwing @@ -2762,8 +2762,8 @@ function Entity:destroy_recursive() end ---@field set_post_get_damage_sound fun(self, fun: fun(self: Movable, damage: DAMAGE_TYPE): SOUNDID?): CallbackId @Hooks after the virtual function.
The callback signature is `nil get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence ---@field set_pre_stun fun(self, fun: fun(self: Movable, framecount: integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool stun(Movable self, integer framecount)` ---@field set_post_stun fun(self, fun: fun(self: Movable, framecount: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil stun(Movable self, integer framecount)` - ---@field set_pre_freeze fun(self, fun: fun(self: Movable, framecount: integer, ignore_lava: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool freeze(Movable self, integer framecount, boolean ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time - ---@field set_post_freeze fun(self, fun: fun(self: Movable, framecount: integer, ignore_lava: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil freeze(Movable self, integer framecount, boolean ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time + ---@field set_pre_freeze fun(self, fun: fun(self: Movable, framecount: integer, ignore_lava: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool freeze(Movable self, integer framecount, boolean ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check,
if in lava the game will set `frozen_timer` to 0 immediately most of the time + ---@field set_post_freeze fun(self, fun: fun(self: Movable, framecount: integer, ignore_lava: boolean): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil freeze(Movable self, integer framecount, boolean ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check,
if in lava the game will set `frozen_timer` to 0 immediately most of the time ---@field set_pre_light_on_fire fun(self, fun: fun(self: Movable, time: integer): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool light_on_fire(Movable self, integer time)`
Virtual function docs:
Does not damage entity ---@field set_post_light_on_fire fun(self, fun: fun(self: Movable, time: integer): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil light_on_fire(Movable self, integer time)`
Virtual function docs:
Does not damage entity ---@field set_pre_set_cursed fun(self, fun: fun(self: Movable, b: boolean, effect: boolean): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool set_cursed(Movable self, boolean b, boolean effect)` diff --git a/docs/parse_source.py b/docs/parse_source.py index 81985c1ef..2d41e09bd 100644 --- a/docs/parse_source.py +++ b/docs/parse_source.py @@ -787,7 +787,7 @@ def run_parse(): ) elif cpp.startswith("[]("): param_match = re.match( - r"\[\]\(([\w &*:,]+)?\) -> ([\w.*&<>\?\[\]:]+)?(?: )?{", cpp + r"\[\]\(([\w &<>\?*:,]+)?\) -> ([\w.*&<>\?\[\]:]+)?(?: )?{", cpp ) if param_match: ret = param_match.group(2) diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 796f23a52..4ffae4ff0 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -4245,7 +4245,7 @@ bool | [overlaps_with(float rect_left, float rect_bottom, float rect_right, floa bool | [overlaps_with(Entity other)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=overlaps_with) | [TEXTURE](#TEXTURE) | [get_texture()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=get_texture) | bool | [set_texture(TEXTURE texture_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_texture) | Changes the entity texture, check the [textures.txt](game_data/textures.txt) for available vanilla textures or use [define_texture](#define_texture) to make custom one -nil | [set_draw_depth(int draw_depth, int b3f)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_draw_depth) | +nil | [set_draw_depth(int draw_depth, optional unknown)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_draw_depth) | nil | [reset_draw_depth()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=reset_draw_depth) | float | [friction()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=friction) | Friction of this entity, affects it's contact with other entities (how fast it slows down on the floor, how fast it can move but also the other way around for floors/activefloors: how other entities can move on it) nil | [liberate_from_shop(bool clear_parrent)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=liberate_from_shop) | `clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought @@ -6974,7 +6974,7 @@ bool | [is_button_pressed(BUTTON button)](https://github.com/spelunky-fyi/overlu bool | [is_button_held(BUTTON button)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_button_held) | bool | [is_button_released(BUTTON button)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=is_button_released) | nil | [stun(int framecount)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=stun) | -nil | [freeze(int framecount, bool ignore_lava)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=freeze) | Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time +nil | [freeze(int framecount, bool ignore_lava)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=freeze) | Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check,
if in lava the game will set `frozen_timer` to 0 immediately most of the time nil | [light_on_fire(int time)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=light_on_fire) | Does not damage entity nil | [set_cursed(bool b, bool effect)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_cursed) | nil | [drop()](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=drop) | Called when dropping or throwing @@ -7038,8 +7038,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_get_damage_sound(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_get_damage_sound) | Hooks after the virtual function.
The callback signature is `nil get_damage_sound(Movable self, DAMAGE_TYPE damage)`
Virtual function docs:
returns sound id for the damage taken, return 0 to make it silence [CallbackId](#Aliases) | [set_pre_stun(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_stun) | Hooks before the virtual function.
The callback signature is `bool stun(Movable self, int framecount)` [CallbackId](#Aliases) | [set_post_stun(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_stun) | Hooks after the virtual function.
The callback signature is `nil stun(Movable self, int framecount)` -[CallbackId](#Aliases) | [set_pre_freeze(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_freeze) | Hooks before the virtual function.
The callback signature is `bool freeze(Movable self, int framecount, bool ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time -[CallbackId](#Aliases) | [set_post_freeze(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_freeze) | Hooks after the virtual function.
The callback signature is `nil freeze(Movable self, int framecount, bool ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time +[CallbackId](#Aliases) | [set_pre_freeze(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_freeze) | Hooks before the virtual function.
The callback signature is `bool freeze(Movable self, int framecount, bool ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check,
if in lava the game will set `frozen_timer` to 0 immediately most of the time +[CallbackId](#Aliases) | [set_post_freeze(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_freeze) | Hooks after the virtual function.
The callback signature is `nil freeze(Movable self, int framecount, bool ignore_lava)`
Virtual function docs:
Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check,
if in lava the game will set `frozen_timer` to 0 immediately most of the time [CallbackId](#Aliases) | [set_pre_light_on_fire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_light_on_fire) | Hooks before the virtual function.
The callback signature is `bool light_on_fire(Movable self, int time)`
Virtual function docs:
Does not damage entity [CallbackId](#Aliases) | [set_post_light_on_fire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_light_on_fire) | Hooks after the virtual function.
The callback signature is `nil light_on_fire(Movable self, int time)`
Virtual function docs:
Does not damage entity [CallbackId](#Aliases) | [set_pre_set_cursed(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_set_cursed) | Hooks before the virtual function.
The callback signature is `bool set_cursed(Movable self, bool b, bool effect)` diff --git a/src/game_api/entity.hpp b/src/game_api/entity.hpp index e9fbb4e73..f39d45d38 100644 --- a/src/game_api/entity.hpp +++ b/src/game_api/entity.hpp @@ -277,16 +277,12 @@ class Entity virtual ~Entity() = 0; // virtual 0 virtual void create_rendering_info() = 0; // 1 virtual void update_state_machine() = 0; // 2 - /// Kills the entity, you can set responsible to `nil` to ignore it virtual void kill(bool destroy_corpse, Entity* responsible) = 0; // 3 - /// Collisions with stuff that blocks you, like walls, floors, etc. Triggers for entities in it's EntityDB.collision_mask virtual void on_collision1(Entity* other_entity) = 0; // 4 - /// Completely removes the entity from existence - virtual void destroy() = 0; // 5 - + virtual void destroy() = 0; // 5 virtual void apply_texture(Texture*) = 0; // 6 virtual void format_shopitem_name(char16_t* output) = 0; // 7 virtual void generate_damage_particles(Entity* victim, DAMAGE_TYPE damage, bool killing) = 0; // 8, contact dmg @@ -302,20 +298,18 @@ class Entity virtual void set_draw_depth(uint8_t draw_depth, uint8_t b3f) = 0; // 17 virtual void reset_draw_depth() = 0; // 18 /// Friction of this entity, affects it's contact with other entities (how fast it slows down on the floor, how fast it can move but also the other way around for floors/activefloors: how other entities can move on it) - virtual float friction() = 0; // 19 - virtual void set_as_sound_source(SoundMeta*) = 0; // 20, update sound position to entity position? + virtual float friction() = 0; // // 19 + virtual void set_as_sound_source(SoundMeta*) = 0; // // 20, update sound position to entity position? /// Can be called multiple times for the same entity (for example when play throws/drops entity from it's hands) virtual void remove_item(Entity* entity, bool autokill_check) = 0; // 21, if autokill_check is true, it will check if the entity has the "kill if overlay lost" flag and kill it if it's set virtual Entity* get_held_entity() = 0; // 22 virtual void v23(Entity* logical_trigger, Entity* who_triggered_it) = 0; // 23, spawns LASERTRAP_SHOT from LASERTRAP, also some trigger entities use this, seam to be called right after "on_collision2", triggers use self as the first parameter. Called when there is entity overlapping trigger entity, even if they don't move /// Triggers weapons and other held items like teleporter, mattock etc. You can check the [virtual-availability.md](https://github.com/spelunky-fyi/overlunky/blob/main/docs/virtual-availability.md), if entity has `open` in the `on_open` you can use this function, otherwise it does nothing. Returns false if action could not be performed (cooldown is not 0, no arrow loaded in etc. the animation could still be played thou) - virtual bool trigger_action(Entity* user) = 0; // 24, also used for throwables, disabling this for bomb make it always spawn an the ground, but you can still pick it up and throw it + virtual bool trigger_action(Entity* user) = 0; // // 24, also used for throwables, disabling this for bomb make it always spawn an the ground, but you can still pick it up and throw it /// Activates a button prompt (with the Use door/Buy button), e.g. buy shop item, activate drill, read sign, interact in camp, ... `get_entity():activate(players[1])` (make sure player 1 has the udjat eye though) - virtual void activate(Entity* activator) = 0; // 25 - + virtual void activate(Entity* activator) = 0; // // 25 /// More like on_overlap, triggers when entities touch/overlap each other. Triggers for entities in it's EntityDB.collision2_mask virtual void on_collision2(Entity* other_entity) = 0; // 26 - /// e.g. for turkey: stores health, poison/curse state, for mattock: remaining swings (returned value is transferred) virtual uint16_t get_metadata() = 0; // 27 virtual void apply_metadata(uint16_t metadata) = 0; // 28 @@ -324,11 +318,10 @@ class Entity virtual void on_ledge_grab(Entity* who) = 0; // 31, only ACTIVEFLOOR_FALLING_PLATFORM, does something with game menager virtual void on_stood_on_by(Entity* entity, Vec2*) = 0; // 32, e.g. pots, skulls, pushblocks, ... standing on floors. The Vec2 is just a guess, it only compares Y with 0.1f /// only for CHAR_*: when going to the backlayer, turns on/off player emitted light - virtual void toggle_backlayer_illumination() = 0; // 33 - virtual void v34() = 0; // 34, only ITEM_TORCH, calls Torch.light_up(false), can't get it to trigger + virtual void toggle_backlayer_illumination() = 0; // // 33 + virtual void v34() = 0; // // 34, only ITEM_TORCH, calls Torch.light_up(false), can't get it to trigger /// `clear_parent` used only for CHAR_* entities, sets the `linked_companion_parent` to -1. It's not called when item is bought virtual void liberate_from_shop(bool clear_parrent) = 0; // 35, can also be seen as event: when you anger the shopkeeper, this function gets called for each item; can be called on shopitems individually as well and they become 'purchased' - /// Applies changes made in `entity.type` virtual void apply_db() = 0; // 36, This is actually just an initialize call that is happening once after the entity is created }; diff --git a/src/game_api/movable.hpp b/src/game_api/movable.hpp index 12ecc5332..52f684a0a 100644 --- a/src/game_api/movable.hpp +++ b/src/game_api/movable.hpp @@ -147,26 +147,24 @@ class Movable : public Entity /// Mostly used for ragdoll by the game virtual void apply_velocity(Vec2* velocities, bool ignore_weight) = 0; // 42 /// Returns the damage that the entity deals - virtual int8_t get_damage() = 0; // 43, for player it calculates stomp damages as that's the only damage that the player entity can deal, the "normal" damage is done by the whip - virtual int8_t get_stomp_damage() = 0; // 44, calls get_damage except for mech which always returns 3, dunno what's the difference between this and get_damage - virtual bool is_on_fire() = 0; // 45 + virtual int8_t get_damage() = 0; // // 43, for player it calculates stomp damages as that's the only damage that the player entity can deal, the "normal" damage is done by the whip + virtual int8_t get_stomp_damage() = 0; // // 44, calls get_damage except for mech which always returns 3, dunno what's the difference between this and get_damage + virtual bool is_on_fire() = 0; // // 45 /// Runs on contact damage, returns false if there wasn't any interaction (called from on_collision2, will be called as long as the hitboxes overlap) - virtual bool attack(Entity* victim) = 0; // 46 + virtual bool attack(Entity* victim) = 0; // // 46 /// Same as above, but for being thrown into something and potentially dealing damage that way - virtual bool thrown_into(Entity* victim) = 0; // 47 - + virtual bool thrown_into(Entity* victim) = 0; // // 47 /// Damage the movable by the specified amount, stuns and gives it invincibility for the specified amount of frames and applies the velocities. `damage_dealer` can be set to nil. /// Returns: true if entity was affected (for stuff like: if pot was thrown into entity, should that pot break after hit), false if the event should be ignored by damage_dealer virtual bool damage(Entity* damage_dealer, int8_t damage_amount, DAMAGE_TYPE damage_flags, Vec2* velocity, uint8_t unknown_damage_phase, uint16_t stun_amount, uint8_t iframes, bool unknown_is_final) = 0; // 48 - /// Hit by broken arrows etc that don't deal damage, calls damage with 0 damage. virtual void on_hit(Entity* damage_dealer) = 0; // 49 /// returns sound id for the damage taken, return 0 to make it silence virtual SOUNDID get_damage_sound(DAMAGE_TYPE damage) = 0; // 50 virtual void stun(uint16_t framecount) = 0; // 51 - /// Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, if in lava the game will set `frozen_timer` to 0 immediately most of the time + /// Sets the `frozen_timer`, the param `ignore_lava` doesn't do much, just skips the liquid check, + /// if in lava the game will set `frozen_timer` to 0 immediately most of the time virtual void freeze(uint8_t framecount, bool ignore_lava) = 0; // 52 - /// Does not damage entity virtual void light_on_fire(uint8_t time) = 0; // 53 virtual void set_cursed(bool b, bool effect) = 0; // 54 @@ -187,8 +185,7 @@ class Movable : public Entity virtual void pick_up(Entity* entity_to_pick_up) = 0; // 67 virtual bool can_be_picked_up_by(Entity* entity_picking_up, bool) = 0; // 68, the bool has something to do with the entity being attached to some entity already /// Called when dropping or throwing - virtual void drop() = 0; // 69 - + virtual void drop() = 0; // // 69 /// Adds or subtracts the specified amount of money to the movable's (player's) inventory. Shows the calculation animation in the HUD. Adds treasure to the inventory list shown on transition. Use the global add_money to add money without adding specific treasure. virtual bool collect_treasure(int32_t value, ENT_TYPE treasure) = 0; // 70 virtual bool apply_movement(uint8_t, uint8_t, uint8_t) = 0; // 71, disable this function and things can't move, some spin in place @@ -201,10 +198,10 @@ class Movable : public Entity virtual void process_input() = 0; // 78, more like: handle_movement virtual void post_collision_damage_related() = 0; // 79, used for enemies attacks as well? 3 versions for: eggplant minister, players and the rest /// Called for entity that just has been picked up - virtual void on_picked_up() = 0; // 80, plays pickup sound depending on the entity mask/type etc. set stun for pets and mounts etc. + virtual void on_picked_up() = 0; // // 80, plays pickup sound depending on the entity mask/type etc. set stun for pets and mounts etc. /// Called for entity that just has been thrown/dropped - virtual void on_release() = 0; // 81, only for hired hands and lava pots, the rest just returns - virtual void generate_fall_poof_particles() = 0; // 82, entity.velocityy must be < -0.12 to generate a poof, might do other stuff regarding falling/landing + virtual void on_release() = 0; // // 81, only for hired hands and lava pots, the rest just returns + virtual void generate_fall_poof_particles() = 0; // // 82, entity.velocityy must be < -0.12 to generate a poof, might do other stuff regarding falling/landing /// Applies gravity to entity. Disable to float like on hoverpack. virtual void handle_fall_logic(float) = 0; // 83, adjusts entity.velocityy when falling virtual void apply_friction(float, bool vertical, float) = 0; // 84, applies entity.type.friction to entity.velocityx, the two floats for characters just multiply the friction, could also be returning the value diff --git a/src/game_api/script/usertypes/entity_lua.cpp b/src/game_api/script/usertypes/entity_lua.cpp index 1274737a3..095f833b7 100644 --- a/src/game_api/script/usertypes/entity_lua.cpp +++ b/src/game_api/script/usertypes/entity_lua.cpp @@ -237,11 +237,10 @@ void register_usertypes(sol::state& lua) entity_type["overlaps_with"] = overlaps_with; entity_type["get_texture"] = &Entity::get_texture; entity_type["set_texture"] = &Entity::set_texture; + /// optional unknown game usually sets it to 0, doesn't appear to have any special effect (needs more reverse engineering) + entity_type["set_draw_depth"] = [](Entity& ent, uint8_t draw_depth, sol::optional unknown) -> void + { ent.set_draw_depth(draw_depth, unknown.value_or(0)); }; // for backward compatibility - auto set_draw_depth = sol::overload(&Entity::set_draw_depth, [](Entity& ent, uint8_t depth) // for backward compatibility - { ent.set_draw_depth(depth, 0); }); - - entity_type["set_draw_depth"] = set_draw_depth; entity_type["reset_draw_depth"] = &Entity::reset_draw_depth; entity_type["friction"] = &Entity::friction; entity_type["set_enable_turning"] = &Entity::set_enable_turning; From 0d42b36ca3a36f896b6210084fe590063fb986f9 Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sat, 14 Dec 2024 18:53:39 +0100 Subject: [PATCH 20/21] rename `generate_fall_poof_particles`, also Floor and Door virtuals using `MemFun` --- src/game_api/movable.hpp | 5 +++-- src/game_api/script/usertypes/vtables_lua.cpp | 17 +++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/game_api/movable.hpp b/src/game_api/movable.hpp index 52f684a0a..8b012db40 100644 --- a/src/game_api/movable.hpp +++ b/src/game_api/movable.hpp @@ -200,8 +200,9 @@ class Movable : public Entity /// Called for entity that just has been picked up virtual void on_picked_up() = 0; // // 80, plays pickup sound depending on the entity mask/type etc. set stun for pets and mounts etc. /// Called for entity that just has been thrown/dropped - virtual void on_release() = 0; // // 81, only for hired hands and lava pots, the rest just returns - virtual void generate_fall_poof_particles() = 0; // // 82, entity.velocityy must be < -0.12 to generate a poof, might do other stuff regarding falling/landing + virtual void on_release() = 0; // // 81, only for hired hands and lava pots, the rest just returns + /// Only for landing on the floor or activefloor, generates "poof" particle and plays sfx (note: when stunned, sfx is played by the damage function) + virtual void generate_landing_effects() = 0; // // 82, entity.velocityy must be < -0.12 to generate a poof, might do other stuff regarding falling/landing /// Applies gravity to entity. Disable to float like on hoverpack. virtual void handle_fall_logic(float) = 0; // 83, adjusts entity.velocityy when falling virtual void apply_friction(float, bool vertical, float) = 0; // 84, applies entity.type.friction to entity.velocityx, the two floats for characters just multiply the friction, could also be returning the value diff --git a/src/game_api/script/usertypes/vtables_lua.cpp b/src/game_api/script/usertypes/vtables_lua.cpp index cc7914ace..227f4924b 100644 --- a/src/game_api/script/usertypes/vtables_lua.cpp +++ b/src/game_api/script/usertypes/vtables_lua.cpp @@ -1,6 +1,7 @@ #include "vtables_lua.hpp" #include "entities_chars.hpp" // for PowerupCapable +#include "entities_floors.hpp" // for Floor #include "entities_items.hpp" // for Powerup and more ... #include "entity.hpp" // for Entity #include "entity_structs.hpp" // for CollisionInfo @@ -118,7 +119,7 @@ void register_usertypes(sol::state& lua) // post_collision_damage_related? VTableEntry<"picked_up", 80, MemFun<&Movable::on_picked_up>>, VTableEntry<"release", 81, MemFun<&Movable::on_release>>, - VTableEntry<"generate_fall_poof_particles", 82, MemFun<&Movable::generate_fall_poof_particles>>, + VTableEntry<"generate_landing_effects", 82, MemFun<&Movable::generate_landing_effects>>, VTableEntry<"fall", 83, MemFun<&Movable::handle_fall_logic>>, VTableEntry<"apply_friction", 84, MemFun<&Movable::apply_friction>>, VTableEntry<"can_break_block", 85, MemFun<&Movable::can_break_block>>, @@ -135,20 +136,20 @@ void register_usertypes(sol::state& lua) Entity, CallbackType::Entity, EntityVTable, - VTableEntry<"floor_update", 0x26, void()>>; + VTableEntry<"floor_update", 0x26, MemFun<&Floor::on_neighbor_destroyed>>>; static FloorVTable floor_vtable(lua, lua["Floor"], "ENTITY_OVERRIDE"); using DoorVTable = HookableVTable< Entity, CallbackType::Entity, EntityVTable, - VTableEntry<"enter_attempt", 40, float(Entity*)>, - VTableEntry<"hide_hud", 41, float(Entity*)>, - VTableEntry<"enter", 42, uint8_t(Entity*)>, + VTableEntry<"enter_attempt", 40, MemFun<&Door::on_enter_attempt>>, + VTableEntry<"hide_hud", 41, MemFun<&Door::hide_ui>>, + VTableEntry<"enter", 42, MemFun<&Door::enter>>, // entered_from_front_layer - VTableEntry<"light_level", 44, float()>, - VTableEntry<"is_unlocked", 45, bool()>, - VTableEntry<"can_enter", 46, bool(Entity*)>>; + VTableEntry<"light_level", 44, MemFun<&Door::light_level>>, + VTableEntry<"is_unlocked", 45, MemFun<&Door::is_unlocked>>, + VTableEntry<"can_enter", 46, MemFun<&Door::can_enter>>>; static DoorVTable door_vtable(lua, lua["Door"], "ENTITY_OVERRIDE"); using RenderInfoVTable = HookableVTable< From 4da0fa83dc7a2d421388ef7fba2ec87ba701162a Mon Sep 17 00:00:00 2001 From: Mr-Auto <36127424+Mr-Auto@users.noreply.github.com> Date: Sat, 14 Dec 2024 19:23:22 +0100 Subject: [PATCH 21/21] rename `acquire` -> `equip`, changes the comment, update docs --- docs/game_data/spel2.lua | 18 +++++++++--------- docs/src/includes/_enums.md | 2 +- docs/src/includes/_types.md | 18 +++++++++--------- src/game_api/entities_items.hpp | 6 +++--- .../script/usertypes/entities_items_lua.cpp | 4 ++-- src/game_api/script/usertypes/vtables_lua.cpp | 2 +- 6 files changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/game_data/spel2.lua b/docs/game_data/spel2.lua index 4e373567a..c18426065 100644 --- a/docs/game_data/spel2.lua +++ b/docs/game_data/spel2.lua @@ -2802,8 +2802,8 @@ function Entity:destroy_recursive() end ---@field set_post_picked_up fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil picked_up(Movable self)`
Virtual function docs:
Called for entity that just has been picked up ---@field set_pre_release fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool release(Movable self)`
Virtual function docs:
Called for entity that just has been thrown/dropped ---@field set_post_release fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil release(Movable self)`
Virtual function docs:
Called for entity that just has been thrown/dropped - ---@field set_pre_generate_fall_poof_particles fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool generate_fall_poof_particles(Movable self)` - ---@field set_post_generate_fall_poof_particles fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil generate_fall_poof_particles(Movable self)` + ---@field set_pre_generate_landing_effects fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool generate_landing_effects(Movable self)`
Virtual function docs:
Only for landing on the floor or activefloor, generates "poof" particle and plays sfx (note: when stunned, sfx is played by the damage function) + ---@field set_post_generate_landing_effects fun(self, fun: fun(self: Movable): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil generate_landing_effects(Movable self)`
Virtual function docs:
Only for landing on the floor or activefloor, generates "poof" particle and plays sfx (note: when stunned, sfx is played by the damage function) ---@field set_pre_fall fun(self, fun: fun(self: Movable, number: number): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool fall(Movable self, number number)`
Virtual function docs:
Applies gravity to entity. Disable to float like on hoverpack. ---@field set_post_fall fun(self, fun: fun(self: Movable, number: number): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil fall(Movable self, number number)`
Virtual function docs:
Applies gravity to entity. Disable to float like on hoverpack. ---@field set_pre_apply_friction fun(self, fun: fun(self: Movable, number: , vertical: boolean, number: ): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool apply_friction(Movable self, number, boolean vertical, number)` @@ -2945,10 +2945,10 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. - ---@field set_pre_enter_attempt fun(self, fun: fun(self: Door, Entity: ): number?): CallbackId @Hooks before the virtual function.
The callback signature is `optional enter_attempt(Door self, Entity)` - ---@field set_post_enter_attempt fun(self, fun: fun(self: Door, Entity: ): number?): CallbackId @Hooks after the virtual function.
The callback signature is `nil enter_attempt(Door self, Entity)` - ---@field set_pre_hide_hud fun(self, fun: fun(self: Door, Entity: ): number?): CallbackId @Hooks before the virtual function.
The callback signature is `optional hide_hud(Door self, Entity)` - ---@field set_post_hide_hud fun(self, fun: fun(self: Door, Entity: ): number?): CallbackId @Hooks after the virtual function.
The callback signature is `nil hide_hud(Door self, Entity)` + ---@field set_pre_enter_attempt fun(self, fun: fun(self: Door, who: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool enter_attempt(Door self, Entity who)` + ---@field set_post_enter_attempt fun(self, fun: fun(self: Door, who: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil enter_attempt(Door self, Entity who)` + ---@field set_pre_hide_hud fun(self, fun: fun(self: Door, who: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool hide_hud(Door self, Entity who)` + ---@field set_post_hide_hud fun(self, fun: fun(self: Door, who: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil hide_hud(Door self, Entity who)` ---@field set_pre_enter fun(self, fun: fun(self: Door, who: Entity): integer?): CallbackId @Hooks before the virtual function.
The callback signature is `optional enter(Door self, Entity who)`
Virtual function docs:
Returns the entity state / behavior id to set the entity to after the entering animation. ---@field set_post_enter fun(self, fun: fun(self: Door, who: Entity): integer?): CallbackId @Hooks after the virtual function.
The callback signature is `nil enter(Door self, Entity who)`
Virtual function docs:
Returns the entity state / behavior id to set the entity to after the entering animation. ---@field set_pre_light_level fun(self, fun: fun(self: Door): number?): CallbackId @Hooks before the virtual function.
The callback signature is `optional light_level(Door self)`
Virtual function docs:
Returns the darkest light level used to fade the entity when entering or exiting. 0 = black, 1 = no change @@ -3825,12 +3825,12 @@ function Movable:generic_update_world(move, sprint_factor, disable_gravity, on_r ---@class Projectile : Movable ---@class Purchasable : Movable - ---@field acquire fun(self, who: Entity): nil @Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money + ---@field equip fun(self, who: Entity): nil @Is called after purchase, changes the DummyPurchasableEntity into the real entity plus tries to equip it, or pick it up (for stuff like weapons), or give the powerup.
Nothing else happens, by itself it does not remove item from shop etc. ---@field set_pre_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks before the virtual function at index `entry`. ---@field set_post_virtual fun(self, entry: ENTITY_OVERRIDE, fun: function): CallbackId @Hooks after the virtual function at index `entry`. ---@field clear_virtual fun(self, callback_id: CallbackId): nil @Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. - ---@field set_pre_acquire fun(self, fun: fun(self: Purchasable, who: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool acquire(Purchasable self, Entity who)`
Virtual function docs:
Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money - ---@field set_post_acquire fun(self, fun: fun(self: Purchasable, who: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil acquire(Purchasable self, Entity who)`
Virtual function docs:
Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money + ---@field set_pre_acquire fun(self, fun: fun(self: Purchasable, who: Entity): boolean): CallbackId @Hooks before the virtual function.
The callback signature is `bool acquire(Purchasable self, Entity who)`
Virtual function docs:
Is called after purchase, changes the DummyPurchasableEntity into the real entity plus tries to equip it, or pick it up (for stuff like weapons), or give the powerup.
Nothing else happens, by itself it does not remove item from shop etc. + ---@field set_post_acquire fun(self, fun: fun(self: Purchasable, who: Entity): boolean): CallbackId @Hooks after the virtual function.
The callback signature is `nil acquire(Purchasable self, Entity who)`
Virtual function docs:
Is called after purchase, changes the DummyPurchasableEntity into the real entity plus tries to equip it, or pick it up (for stuff like weapons), or give the powerup.
Nothing else happens, by itself it does not remove item from shop etc. ---@class DummyPurchasableEntity : Purchasable ---@field replace_entity Entity diff --git a/docs/src/includes/_enums.md b/docs/src/includes/_enums.md index 74ffffd4a..3e7319d9c 100644 --- a/docs/src/includes/_enums.md +++ b/docs/src/includes/_enums.md @@ -286,7 +286,7 @@ Name | Data | Description [PROCESS_INPUT](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.PROCESS_INPUT) | 78 | [PICKED_UP](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.PICKED_UP) | 80 | [RELEASE](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.RELEASE) | 81 | -[GENERATE_FALL_POOF_PARTICLES](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GENERATE_FALL_POOF_PARTICLES) | 82 | +[GENERATE_LANDING_EFFECTS](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.GENERATE_LANDING_EFFECTS) | 82 | [FALL](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.FALL) | 83 | [APPLY_FRICTION](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.APPLY_FRICTION) | 84 | [CAN_BREAK_BLOCK](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=ENTITY_OVERRIDE.CAN_BREAK_BLOCK) | 85 | diff --git a/docs/src/includes/_types.md b/docs/src/includes/_types.md index 4ffae4ff0..fd45dfc35 100644 --- a/docs/src/includes/_types.md +++ b/docs/src/includes/_types.md @@ -3812,10 +3812,10 @@ nil | [unlock(bool unlock)](https://github.com/spelunky-fyi/overlunky/search?l=L [CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. [CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. -[CallbackId](#Aliases) | [set_pre_enter_attempt(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_enter_attempt) | Hooks before the virtual function.
The callback signature is `optional enter_attempt(Door self, Entity)` -[CallbackId](#Aliases) | [set_post_enter_attempt(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_enter_attempt) | Hooks after the virtual function.
The callback signature is `nil enter_attempt(Door self, Entity)` -[CallbackId](#Aliases) | [set_pre_hide_hud(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_hide_hud) | Hooks before the virtual function.
The callback signature is `optional hide_hud(Door self, Entity)` -[CallbackId](#Aliases) | [set_post_hide_hud(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_hide_hud) | Hooks after the virtual function.
The callback signature is `nil hide_hud(Door self, Entity)` +[CallbackId](#Aliases) | [set_pre_enter_attempt(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_enter_attempt) | Hooks before the virtual function.
The callback signature is `bool enter_attempt(Door self, Entity who)` +[CallbackId](#Aliases) | [set_post_enter_attempt(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_enter_attempt) | Hooks after the virtual function.
The callback signature is `nil enter_attempt(Door self, Entity who)` +[CallbackId](#Aliases) | [set_pre_hide_hud(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_hide_hud) | Hooks before the virtual function.
The callback signature is `bool hide_hud(Door self, Entity who)` +[CallbackId](#Aliases) | [set_post_hide_hud(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_hide_hud) | Hooks after the virtual function.
The callback signature is `nil hide_hud(Door self, Entity who)` [CallbackId](#Aliases) | [set_pre_enter(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_enter) | Hooks before the virtual function.
The callback signature is `optional enter(Door self, Entity who)`
Virtual function docs:
Returns the entity state / behavior id to set the entity to after the entering animation. [CallbackId](#Aliases) | [set_post_enter(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_enter) | Hooks after the virtual function.
The callback signature is `nil enter(Door self, Entity who)`
Virtual function docs:
Returns the entity state / behavior id to set the entity to after the entering animation. [CallbackId](#Aliases) | [set_pre_light_level(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_light_level) | Hooks before the virtual function.
The callback signature is `optional light_level(Door self)`
Virtual function docs:
Returns the darkest light level used to fade the entity when entering or exiting. 0 = black, 1 = no change @@ -7078,8 +7078,8 @@ nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/ov [CallbackId](#Aliases) | [set_post_picked_up(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_picked_up) | Hooks after the virtual function.
The callback signature is `nil picked_up(Movable self)`
Virtual function docs:
Called for entity that just has been picked up [CallbackId](#Aliases) | [set_pre_release(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_release) | Hooks before the virtual function.
The callback signature is `bool release(Movable self)`
Virtual function docs:
Called for entity that just has been thrown/dropped [CallbackId](#Aliases) | [set_post_release(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_release) | Hooks after the virtual function.
The callback signature is `nil release(Movable self)`
Virtual function docs:
Called for entity that just has been thrown/dropped -[CallbackId](#Aliases) | [set_pre_generate_fall_poof_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_generate_fall_poof_particles) | Hooks before the virtual function.
The callback signature is `bool generate_fall_poof_particles(Movable self)` -[CallbackId](#Aliases) | [set_post_generate_fall_poof_particles(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_generate_fall_poof_particles) | Hooks after the virtual function.
The callback signature is `nil generate_fall_poof_particles(Movable self)` +[CallbackId](#Aliases) | [set_pre_generate_landing_effects(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_generate_landing_effects) | Hooks before the virtual function.
The callback signature is `bool generate_landing_effects(Movable self)`
Virtual function docs:
Only for landing on the floor or activefloor, generates "poof" particle and plays sfx (note: when stunned, sfx is played by the damage function) +[CallbackId](#Aliases) | [set_post_generate_landing_effects(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_generate_landing_effects) | Hooks after the virtual function.
The callback signature is `nil generate_landing_effects(Movable self)`
Virtual function docs:
Only for landing on the floor or activefloor, generates "poof" particle and plays sfx (note: when stunned, sfx is played by the damage function) [CallbackId](#Aliases) | [set_pre_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_fall) | Hooks before the virtual function.
The callback signature is `bool fall(Movable self, float float)`
Virtual function docs:
Applies gravity to entity. Disable to float like on hoverpack. [CallbackId](#Aliases) | [set_post_fall(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_fall) | Hooks after the virtual function.
The callback signature is `nil fall(Movable self, float float)`
Virtual function docs:
Applies gravity to entity. Disable to float like on hoverpack. [CallbackId](#Aliases) | [set_pre_apply_friction(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_apply_friction) | Hooks before the virtual function.
The callback signature is `bool apply_friction(Movable self, float, bool vertical, float)` @@ -7278,12 +7278,12 @@ Derived from [Entity](#Entity) [Movable](#Movable) Type | Name | Description ---- | ---- | ----------- -nil | [acquire(Entity who)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=acquire) | Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money +nil | [equip(Entity who)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=equip) | Is called after purchase, changes the [DummyPurchasableEntity](#DummyPurchasableEntity) into the real entity plus tries to equip it, or pick it up (for stuff like weapons), or give the powerup.
Nothing else happens, by itself it does not remove item from shop etc. [CallbackId](#Aliases) | [set_pre_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_virtual) | Hooks before the virtual function at index `entry`. [CallbackId](#Aliases) | [set_post_virtual(ENTITY_OVERRIDE entry, function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_virtual) | Hooks after the virtual function at index `entry`. nil | [clear_virtual(CallbackId callback_id)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=clear_virtual) | Clears the hook given by `callback_id`, alternatively use `clear_callback()` inside the hook. -[CallbackId](#Aliases) | [set_pre_acquire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_acquire) | Hooks before the virtual function.
The callback signature is `bool acquire(Purchasable self, Entity who)`
Virtual function docs:
Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money -[CallbackId](#Aliases) | [set_post_acquire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_acquire) | Hooks after the virtual function.
The callback signature is `nil acquire(Purchasable self, Entity who)`
Virtual function docs:
Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop.
does not consume money +[CallbackId](#Aliases) | [set_pre_acquire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_pre_acquire) | Hooks before the virtual function.
The callback signature is `bool acquire(Purchasable self, Entity who)`
Virtual function docs:
Is called after purchase, changes the DummyPurchasableEntity into the real entity plus tries to equip it, or pick it up (for stuff like weapons), or give the powerup.
Nothing else happens, by itself it does not remove item from shop etc. +[CallbackId](#Aliases) | [set_post_acquire(function fun)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_post_acquire) | Hooks after the virtual function.
The callback signature is `nil acquire(Purchasable self, Entity who)`
Virtual function docs:
Is called after purchase, changes the DummyPurchasableEntity into the real entity plus tries to equip it, or pick it up (for stuff like weapons), or give the powerup.
Nothing else happens, by itself it does not remove item from shop etc. ### PushBlock diff --git a/src/game_api/entities_items.hpp b/src/game_api/entities_items.hpp index 7245214ff..caecf8891 100644 --- a/src/game_api/entities_items.hpp +++ b/src/game_api/entities_items.hpp @@ -100,9 +100,9 @@ class VladsCape : public Cape class Purchasable : public Movable { public: - /// Be aware that for pickable items like weapons, the item will be automatically picked up by the player (unless he already holds something), the ownership transfer is a little bit slow, so it might trigger the shop keeper if you're not inside the shop. - /// does not consume money - virtual void acquire(Entity* who) = 0; + /// Is called after purchase, changes the DummyPurchasableEntity into the real entity plus tries to equip it, or pick it up (for stuff like weapons), or give the powerup. + /// Nothing else happens, by itself it does not remove item from shop etc. + virtual void equip(Entity* who) = 0; }; class DummyPurchasableEntity : public Purchasable diff --git a/src/game_api/script/usertypes/entities_items_lua.cpp b/src/game_api/script/usertypes/entities_items_lua.cpp index 045d38c2b..dd8c8ed44 100644 --- a/src/game_api/script/usertypes/entities_items_lua.cpp +++ b/src/game_api/script/usertypes/entities_items_lua.cpp @@ -155,8 +155,8 @@ void register_usertypes(sol::state& lua) lua.new_usertype( "Purchasable", - "acquire", - &Purchasable::acquire, + "equip", + &Purchasable::equip, sol::base_classes, sol::bases()); diff --git a/src/game_api/script/usertypes/vtables_lua.cpp b/src/game_api/script/usertypes/vtables_lua.cpp index 227f4924b..b2827c2a4 100644 --- a/src/game_api/script/usertypes/vtables_lua.cpp +++ b/src/game_api/script/usertypes/vtables_lua.cpp @@ -194,7 +194,7 @@ void register_usertypes(sol::state& lua) Entity, CallbackType::Entity, EntityVTable, - VTableEntry<"acquire", 93, MemFun<&Purchasable::acquire>>>; + VTableEntry<"acquire", 93, MemFun<&Purchasable::equip>>>; static PurchasableVTable purchasable_vtable(lua, lua["Purchasable"], "ENTITY_OVERRIDE"); using DummyPurchasableEntityVTable = HookableVTable<