Skip to content

Commit

Permalink
Some random changes (#251)
Browse files Browse the repository at this point in the history
* Add utility for straight up using Ghidra byte strings

* Clarify some structure in Entity/EntityDB

* Add missing members to RenderInfo

* Add get_max_rope_length

* Add return to spawn_tree, plus typo fixes

* Fix in info_dump

* Disable static assert for MSVC

* First draft of spawn rope

* Update docs

* Clang fix number one

* Formatting fixes

* Add missing new line at EOF

* MrAuto requests

* Second draft for rope spawn

* Add interface to disable all hooks

* Tag vanilla machine rooms with a special tag

* Add util for super lazy people

* Crazy code to allow making single entities climbable

* Fix wrong param in update_movable

* Add base_behavior binding

* Split entity.hpp/.cpp into three

* Add API to disable turning, useful when doing custom state machines and turning logic fudges with the result

* Add missing patterns

* Fix CI

* clone types, no crazy code

* Relax construct and destroy interface on allocators

* Change hasher on EntityDB::animations

* Automated clang-format changes

* Remove set_climbable and other unnecessary stuff

* some documentation for EntityDB

* Fix for missing _ENV in some callbacks

* Update docs

* clang clang

* Add new line at EOF

Co-authored-by: Dregu <[email protected]>
Co-authored-by: Clang-Format Bot <[email protected]>
  • Loading branch information
3 people authored Sep 3, 2022
1 parent a887896 commit b442ddd
Show file tree
Hide file tree
Showing 48 changed files with 2,286 additions and 1,475 deletions.
59 changes: 59 additions & 0 deletions docs/examples/EntityDB.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
Used to store static common data for an ENT_TYPE. You can also clone entity types with the copy constructor to create new custom entities with different common properties. [This tool](https://dregu.github.io/Spelunky2ls/animation.html) can be helpful when messing with the animations. The default values are also listed in [entities.json](https://github.com/spelunky-fyi/overlunky/blob/main/docs/game_data/entities.json).

> When cloning an entity type, remember to save it in the script for as long as you need it. Otherwise the memory will be freed immediately, which eventually leads to a crash when used or overwritten by other stuff:
```lua
-- Create a special fast snake type with weird animation
special_snake = EntityDB:new(ENT_TYPE.MONS_SNAKE)
special_snake.max_speed = 1
special_snake.acceleration = 2
special_snake.animations[2].num_tiles = 1

set_post_entity_spawn(function(snake)
-- 50% chance to make snakes special
if prng:random_chance(2, PRNG_CLASS.PROCEDURAL_SPAWNS) then
-- Assign custom type
snake.type = special_snake
-- This is only really needed if types are changed during the level
snake.current_animation = special_snake.animations[2]
end
end, SPAWN_TYPE.ANY, MASK.MONSTER, ENT_TYPE.MONS_SNAKE)
```

> You can also use Entity.user_data to store the custom type:
```lua
-- Custom player who is buffed a bit every level
set_callback(function()
-- Doing this to include HH
for i,v in ipairs(get_entities_by_mask(MASK.PLAYER)) do
local player = get_entity(v)

-- Create new custom type on the first level, based on the original type
if not player.user_data then
player.user_data = {}
player.user_data.type = EntityDB:new(player.type.id)
end

-- Set the player entity type to the custom type every level
player.type = player.user_data.type

-- Buff the player every subsequent level
if state.level_count > 0 then
player.type.max_speed = player.type.max_speed * 1.1
player.type.acceleration = player.type.acceleration * 1.1
player.type.jump = player.type.jump * 1.1
end
end
end, ON.POST_LEVEL_GENERATION)
```

> Illegal bad example, don't do this:
```lua
set_callback(function()
-- Nobody owns the new type and the memory is freed immediately, eventually leading to a crash
players[1].type = EntityDB:new(players[1].type)
players[1].type.max_speed = 2
end, ON.POST_LEVEL_GENERATION)
```
34 changes: 30 additions & 4 deletions docs/game_data/spel2.lua

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions docs/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
"vector<": "array<",
"span<": "array<",
"unordered_map<": "map<",
"game_map<": "map<",
", identity_hasher<>": "",
"const char*": "string",
"wstring": "string",
"u16string": "string",
Expand Down
2 changes: 2 additions & 0 deletions docs/generate_emmylua.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"vector": "Array",
"array": "Array",
"unordered_map": "table",
"game_table": "table",
", identity_hasher<>": "",
"const char*": "string",
"wstring": "string",
"u16string": "string",
Expand Down
2 changes: 2 additions & 0 deletions docs/parse_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
"../src/game_api/script.hpp",
"../src/game_api/color.hpp",
"../src/game_api/entity.hpp",
"../src/game_api/entity_db.hpp",
"../src/game_api/entity_structs.hpp",
"../src/game_api/movable.hpp",
"../src/game_api/movable_behavior.hpp",
"../src/game_api/game_manager.hpp",
Expand Down
17 changes: 14 additions & 3 deletions docs/src/includes/_globals.md
Original file line number Diff line number Diff line change
Expand Up @@ -2237,7 +2237,7 @@ Spawn a [RoomOwner](#RoomOwner) (or a few other like CavemanShopkeeper) in the c

> Search script examples for [add_item_to_shop](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=add_item_to_shop)
#### nil add_item_to_shop(int item_uid, int shop_owner)
#### nil add_item_to_shop(int item_uid, int shop_owner_uid)

Adds entity as shop item, has to be movable (haven't tested many)

Expand Down Expand Up @@ -2620,12 +2620,23 @@ If you want to respawn a player that is a ghost, set in his inventory `health` t

> Search script examples for [spawn_tree](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_tree)
#### nil spawn_tree(float x, float y, [LAYER](#LAYER) layer)
#### int spawn_tree(float x, float y, [LAYER](#LAYER) layer)

#### nil spawn_tree(float x, float y, [LAYER](#LAYER) layer, int height)
#### int spawn_tree(float x, float y, [LAYER](#LAYER) layer, int height)

Spawns and grows a tree

### spawn_unrolled_player_rope


> Search script examples for [spawn_unrolled_player_rope](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=spawn_unrolled_player_rope)
#### int spawn_unrolled_player_rope(float x, float y, [LAYER](#LAYER) layer, [TEXTURE](#TEXTURE) texture)

#### int spawn_unrolled_player_rope(float x, float y, [LAYER](#LAYER) layer, [TEXTURE](#TEXTURE) texture, int max_length)

Spawns an already unrolled rope as if created by player

## String functions


Expand Down
69 changes: 68 additions & 1 deletion docs/src/includes/_types.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,13 +287,14 @@ int | [target_uid](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=targ
int | [timer](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=timer) |
int | [state](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=state) | AI state (patrol, sleep, attack, aggro...)
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) | How many times master has violated us
int | [whipped](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=whipped) | Number of times whipped by player

### Animation


Type | Name | Description
---- | ---- | -----------
int | [id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=id) |
int | [first_tile](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=first_tile) |
int | [num_tiles](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=num_tiles) |
int | [interval](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=interval) |
Expand All @@ -302,8 +303,72 @@ int | [interval](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=interv
### EntityDB


Used to store static common data for an ENT_TYPE. You can also clone entity types with the copy constructor to create new custom entities with different common properties. [This tool](https://dregu.github.io/Spelunky2ls/animation.html) can be helpful when messing with the animations. The default values are also listed in [entities.json](https://github.com/spelunky-fyi/overlunky/blob/main/docs/game_data/entities.json).

> When cloning an entity type, remember to save it in the script for as long as you need it. Otherwise the memory will be freed immediately, which eventually leads to a crash when used or overwritten by other stuff:
```lua
-- Create a special fast snake type with weird animation
special_snake = EntityDB:new(ENT_TYPE.MONS_SNAKE)
special_snake.max_speed = 1
special_snake.acceleration = 2
special_snake.animations[2].num_tiles = 1

set_post_entity_spawn(function(snake)
-- 50% chance to make snakes special
if prng:random_chance(2, PRNG_CLASS.PROCEDURAL_SPAWNS) then
-- Assign custom type
snake.type = special_snake
-- This is only really needed if types are changed during the level
snake.current_animation = special_snake.animations[2]
end
end, SPAWN_TYPE.ANY, MASK.MONSTER, ENT_TYPE.MONS_SNAKE)
```

> You can also use Entity.user_data to store the custom type:
```lua
-- Custom player who is buffed a bit every level
set_callback(function()
-- Doing this to include HH
for i,v in ipairs(get_entities_by_mask(MASK.PLAYER)) do
local player = get_entity(v)

-- Create new custom type on the first level, based on the original type
if not player.user_data then
player.user_data = {}
player.user_data.type = EntityDB:new(player.type.id)
end

-- Set the player entity type to the custom type every level
player.type = player.user_data.type

-- Buff the player every subsequent level
if state.level_count > 0 then
player.type.max_speed = player.type.max_speed * 1.1
player.type.acceleration = player.type.acceleration * 1.1
player.type.jump = player.type.jump * 1.1
end
end
end, ON.POST_LEVEL_GENERATION)
```

> Illegal bad example, don't do this:
```lua
set_callback(function()
-- Nobody owns the new type and the memory is freed immediately, eventually leading to a crash
players[1].type = EntityDB:new(players[1].type)
players[1].type.max_speed = 2
end, ON.POST_LEVEL_GENERATION)
```



Type | Name | Description
---- | ---- | -----------
[EntityDB](#EntityDB) | [new(EntityDB other)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=EntityDB) |
[EntityDB](#EntityDB) | [new(ENT_TYPE)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=EntityDB) |
[ENT_TYPE](#ENT_TYPE) | [id](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=id) |
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) |
Expand Down Expand Up @@ -3111,6 +3176,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)](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) |
[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
Expand Down Expand Up @@ -4864,6 +4930,7 @@ Derived from [MovableBehavior](#MovableBehavior)

Type | Name | Description
---- | ---- | -----------
[VanillaMovableBehavior](#VanillaMovableBehavior) | [base_behavior](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=base_behavior) |
nil | [set_force_state(function force_state)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_force_state) | Set the `force_state` function of a `CustomMovableBehavior`, this will be called every frame when<br/>the movable is updated. If an `force_state` is already set it will be overridden. The signature<br/>of the function is `bool force_state(movable, base_fun)`, when the function returns `true` the movable will<br/>enter this behavior. If no base behavior is set `base_fun` will be `nil`.
nil | [set_on_enter(function on_enter)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_on_enter) | Set the `on_enter` function of a `CustomMovableBehavior`, this will be called when the movable<br/>enters the state. If an `on_enter` is already set it will be overridden. The signature of the<br/>function is `nil on_enter(movable, base_fun))`. If no base behavior is set `base_fun` will be `nil`.
nil | [set_on_exit(function on_exit)](https://github.com/spelunky-fyi/overlunky/search?l=Lua&q=set_on_exit) | Set the `on_exit` function of a `CustomMovableBehavior`, this will be called when the movable<br/>leaves the state. If an `on_exit` is already set it will be overridden. The signature of the<br/>function is `nil on_exit(movable, base_fun))`. If no base behavior is set `base_fun` will be `nil`.
Expand Down
10 changes: 6 additions & 4 deletions src/game_api/containers/custom_allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,15 @@ struct custom_allocator
new (static_cast<void*>(p)) T(val);
}

void construct(pointer p)
template <class U, class... Args>
void construct(U* const p, Args&&... args)
{
new (static_cast<void*>(p)) T();
new (static_cast<void*>(p)) U(std::forward<Args>(args)...);
}

void destroy(pointer p)
template <class U>
void destroy(U* const p)
{
p->~T();
p->~U();
}
};
15 changes: 6 additions & 9 deletions src/game_api/containers/game_allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,15 @@ struct game_allocator
game_free(p);
}

void construct(pointer p, const T& val)
template <class U, class... Args>
void construct(U* const p, Args&&... args)
{
new (static_cast<void*>(p)) T(val);
new (static_cast<void*>(p)) U(std::forward<Args>(args)...);
}

void construct(pointer p)
{
new (static_cast<void*>(p)) T();
}

void destroy(pointer p)
template <class U>
void destroy(U* const p)
{
p->~T();
p->~U();
}
};
4 changes: 2 additions & 2 deletions src/game_api/containers/game_unordered_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

#include <unordered_map>

template <class K, class V>
using game_unordered_map = std::unordered_map<K, V, std::hash<K>, std::equal_to<K>, game_allocator<std::pair<const K, V>>>;
template <class K, class V, class Hasher = std::hash<K>, class Equal = std::equal_to<K>>
using game_unordered_map = std::unordered_map<K, V, Hasher, Equal, game_allocator<std::pair<const K, V>>>;
23 changes: 23 additions & 0 deletions src/game_api/containers/identity_hasher.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

#include <cstddef>
#include <type_traits>

template <class T = void>
struct identity_hasher
{
[[nodiscard]] size_t operator()(const T& val) const noexcept
{
return static_cast<size_t>(val);
}
};

template <>
struct identity_hasher<void>
{
template <class T>
[[nodiscard]] size_t operator()(const T& val) const noexcept
{
return static_cast<size_t>(val);
}
};
Loading

0 comments on commit b442ddd

Please sign in to comment.