Compare commits

..

10 commits

Author SHA1 Message Date
Sara 208743c2f1 chore(git): added kdev files to gitignore 2024-09-10 09:49:58 +02:00
Sara f67f95fd6a feat: added animation events to animation_sprite 2024-09-10 09:48:37 +02:00
Sara a63cfdd2b0 chore: updated utils 2024-09-10 09:48:12 +02:00
Sara 3d3d95030b feat: removed leftover list.c 2024-02-28 11:32:24 +01:00
Sara 5edea42188 feat: updated utils 2024-02-28 11:31:27 +01:00
Sara b641589188 feat: renamed LevelSpawnFn to DeserializeFn 2024-02-22 21:12:34 +01:00
Sara 630f60af94 chore: formatting cleanup in animation_sprite.c 2024-02-22 21:12:20 +01:00
Sara 6b8dbaee7b feat: added out list argument to HurtboxCast 2024-02-22 21:12:07 +01:00
Sara 2895ce6079 feat: adjusted reflect macros to work with eaten semicolons\ 2024-02-22 14:59:35 +01:00
Sara c50a3f3563 feat: updated utils 2024-02-22 14:54:16 +01:00
14 changed files with 141 additions and 272 deletions

2
.gitignore vendored
View file

@ -12,3 +12,5 @@ Makefile
.vs
.idea
*.sln
.kdev4
fencer.kdev4

View file

@ -1,47 +1,63 @@
#include "animation_sprite.h"
#include "debug.h"
#include "program.h"
#include "list.h"
struct AnimationSprite {
Spritesheet* sheet;
Sprite* sprite_target;
Spritesheet *sheet;
Sprite *sprite_target;
AnimationSpriteLoopMode loop_mode;
AnimationSpriteLoopMode loop_mode;
float frame_interval;
float start_time;
float frame_interval;
float start_time;
size_t event_index;
List events;
};
AnimationSprite* animation_sprite_new(Sprite* target_sprite, Spritesheet* sheet, float framerate, AnimationSpriteLoopMode loop_mode) {
AnimationSprite* self = malloc(sizeof(AnimationSprite));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate memory for AnimationSprite");
*self = (AnimationSprite){
.sheet = sheet,
.frame_interval = 1.0f / framerate,
.loop_mode = loop_mode,
.start_time = game_time(),
.sprite_target = target_sprite
};
return self;
AnimationSprite *animation_sprite_new(Sprite *target_sprite, Spritesheet *sheet,
float framerate, AnimationSpriteLoopMode loop_mode,
AnimationEvent *events, size_t event_count) {
AnimationSprite *self = malloc(sizeof(AnimationSprite));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate memory for AnimationSprite");
*self = (AnimationSprite){
.sheet = sheet,
.frame_interval = 1.0f / framerate,
.loop_mode = loop_mode,
.start_time = game_time(),
.sprite_target = target_sprite,
.event_index = 0,
.events = list_with_len(sizeof(AnimationEvent), event_count),
};
if(event_count > 0) {
memcpy(self->events.data, events, sizeof(AnimationEvent) * event_count);
self->events.len = event_count;
}
return self;
}
void animation_sprite_destroy(AnimationSprite* self) {
spritesheet_destroy(self->sheet);
free(self);
void animation_sprite_destroy(AnimationSprite *self) {
spritesheet_destroy(self->sheet);
free(self);
}
void animation_sprite_play_from(AnimationSprite* self, float normalized_time) {
self->start_time = game_time() - normalized_time * animation_sprite_get_length(self);
void animation_sprite_reset(AnimationSprite *self) {
self->start_time = game_time();
}
void animation_sprite_draw(AnimationSprite* self, Transform* transform) {
void animation_sprite_play_from(AnimationSprite *self, float normalized_time) {
self->start_time = game_time() - normalized_time * animation_sprite_get_length(self);
}
void animation_sprite_draw(AnimationSprite *self, Transform *transform) {
const size_t frame_count = spritesheet_get_tile_count(self->sheet);
const float time = game_time() - self->start_time;
const float time = game_time() - self->start_time;
size_t frame = (size_t)(time / self->frame_interval);
switch(self->loop_mode) {
case LoopMode_Stop:
if(frame >= frame_count)
frame = frame_count - 1;
case LoopMode_Hide:
if(frame >= frame_count)
return;
@ -55,36 +71,44 @@ void animation_sprite_draw(AnimationSprite* self, Transform* transform) {
if(frame >= frame_count)
frame = frame_count - (frame - frame_count);
return;
case LoopMode_Stop:
if(frame >= frame_count)
frame = frame_count - 1;
}
sprite_set_spritesheet(self->sprite_target, self->sheet);
sprite_set_tile(self->sprite_target, frame);
sprite_draw(self->sprite_target, *transform);
sprite_set_tile(self->sprite_target, frame);
sprite_draw(self->sprite_target, *transform);
}
float animation_sprite_get_length(AnimationSprite* self) {
return (float)spritesheet_get_tile_count(self->sheet) * self->frame_interval;
void animation_sprite_update_events(AnimationSprite *self) {
const float current_time = game_time() - self->start_time;
for(;self->event_index <= self->events.len; ++self->event_index) {
AnimationEvent *event = list_at_as(AnimationEvent, &self->events, self->event_index);
if(event->time < current_time)
return;
else
event->fn(event->target, event->arg.data);
}
}
void animation_sprite_set_framerate(AnimationSprite* self, float framerate) {
self->frame_interval = 1.0f / framerate;
float animation_sprite_get_length(AnimationSprite *self) {
return (float)spritesheet_get_tile_count(self->sheet) * self->frame_interval;
}
float animation_sprite_get_framerate(const AnimationSprite* self) {
return 1.0f / self->frame_interval;
void animation_sprite_set_framerate(AnimationSprite *self, float framerate) {
self->frame_interval = 1.0f / framerate;
}
Sprite* animation_sprite_get_sprite(AnimationSprite* self) {
float animation_sprite_get_framerate(const AnimationSprite *self) {
return 1.0f / self->frame_interval;
}
Sprite *animation_sprite_get_sprite(AnimationSprite *self) {
return self->sprite_target;
}
float animation_sprite_get_time(AnimationSprite* self) {
float animation_sprite_get_time(AnimationSprite *self) {
return game_time() - self->start_time;
}
float animation_sprite_get_time_normalized(AnimationSprite* self) {
float animation_sprite_get_time_normalized(AnimationSprite *self) {
return animation_sprite_get_time(self) / animation_sprite_get_length(self);
}

View file

@ -1,6 +1,7 @@
#ifndef _fencer_animation_sprite_h
#define _fencer_animation_sprite_h
#include "drop.h"
#include "sprite.h"
#include "spritesheet.h"
@ -11,19 +12,31 @@ typedef enum AnimationSpriteLoopMode {
LoopMode_PingPong,
} AnimationSpriteLoopMode;
typedef void (*AnimationEventFn)(void *object, void *arg);
typedef struct AnimationEvent {
float time;
void *target;
Drop arg;
AnimationEventFn fn;
} AnimationEvent;
typedef struct AnimationSprite AnimationSprite;
extern AnimationSprite* animation_sprite_new(Sprite* target_sprite, Spritesheet* sheet, float framerate, AnimationSpriteLoopMode loop_mode);
extern void animation_sprite_destroy(AnimationSprite* self);
extern AnimationSprite *animation_sprite_new(Sprite *target_sprite, Spritesheet *sheet, float framerate, AnimationSpriteLoopMode loop_mode, AnimationEvent *events, size_t event_count);
extern void animation_sprite_destroy(AnimationSprite *self);
extern void animation_sprite_play_from(AnimationSprite* self, float normalized_time);
extern void animation_sprite_draw(AnimationSprite* self, Transform* transform);
extern void animation_sprite_reset(AnimationSprite *self);
extern void animation_sprite_play_from(AnimationSprite *self, float normalized_time);
extern void animation_sprite_draw(AnimationSprite *self, Transform *transform);
extern float animation_sprite_get_length(AnimationSprite* self);
extern void animation_sprite_set_framerate(AnimationSprite* self, float framerate);
extern float animation_sprite_get_framerate(const AnimationSprite* self);
extern Sprite* animation_sprite_get_sprite(AnimationSprite* self);
extern float animation_sprite_get_time(AnimationSprite* self);
extern float animation_sprite_get_time_normalized(AnimationSprite* self);
extern void animation_sprite_update_events(AnimationSprite *self);
extern float animation_sprite_get_length(AnimationSprite *self);
extern void animation_sprite_set_framerate(AnimationSprite *self, float framerate);
extern float animation_sprite_get_framerate(const AnimationSprite *self);
extern Sprite *animation_sprite_get_sprite(AnimationSprite *self);
extern float animation_sprite_get_time(AnimationSprite *self);
extern float animation_sprite_get_time_normalized(AnimationSprite *self);
#endif // !_fencer_animation_sprite_h

View file

@ -6,7 +6,7 @@
#include "variant.h"
#include "ctype.h"
static Dictionary internal_spawn_functions = {
static Dictionary internal_deserializers = {
.list = { .data = NULL, .len = 0, .cap = 0, .element_size = 0 },
.element_size = 0
};
@ -17,22 +17,22 @@ static int is_colon(int c) { return c == ':'; }
static int ends_parameter(int c) { return c == '}' || c == ','; }
int level_init() {
internal_spawn_functions = dictionary_from_type(LevelSpawnFn);
internal_deserializers = dictionary_from_type(DeserializeFn);
return 0;
}
int level_clean() {
dictionary_empty(&internal_spawn_functions);
dictionary_empty(&internal_deserializers);
return 0;
}
int level_register_spawner(const char* object_tag, LevelSpawnFn spawn_function) {
dictionary_set_value(LevelSpawnFn, &internal_spawn_functions, object_tag, spawn_function);
int level_register_spawner(const char* object_tag, DeserializeFn spawn_function) {
dictionary_set_value(DeserializeFn, &internal_deserializers, object_tag, spawn_function);
return 0;
}
static inline
void spawn_object(LevelSpawnFn spawner, Dictionary* args) {
void spawn_object(DeserializeFn spawner, Dictionary* args) {
BehaviourEntity entity = spawner(args);
game_world_add_entity(entity);
if(TC_MIRRORS(entity, PhysicsEntity))
@ -140,7 +140,7 @@ int level_parse_file(FILE* fp) {
char buffer[length];
char* obj_tag = NULL;
Dictionary args = dictionary_new(sizeof(Variant));
LevelSpawnFn spawner = NULL;
DeserializeFn spawner = NULL;
do {
// read the next line of the level file
length = get_until(fp, buffer, sizeof(buffer)-1, is_open_bracket);
@ -152,7 +152,7 @@ int level_parse_file(FILE* fp) {
obj_tag[length - start] = '\0';
strncpy(obj_tag, buffer + start, length - start);
// find the spawn function
if(dictionary_try_get(&internal_spawn_functions, obj_tag, &spawner)) {
if(dictionary_try_get(&internal_deserializers, obj_tag, &spawner)) {
// load arguments from file and spawn object
load_args(fp, &args, buffer, sizeof(buffer));
spawn_object(spawner, &args);

View file

@ -5,12 +5,12 @@
#include "behaviour_entity.h"
#include "dictionary.h"
typedef BehaviourEntity(*LevelSpawnFn)(Dictionary* args);
typedef BehaviourEntity(*DeserializeFn)(Dictionary* args);
extern int level_init();
extern int level_clean();
extern int level_register_spawner(const char* object_tag, LevelSpawnFn spawn_function);
extern int level_register_spawner(const char* object_tag, DeserializeFn spawn_function);
extern int level_parse_file(FILE* level);
extern int level_load_file(const char* path);

View file

@ -1,176 +0,0 @@
#include "list.h"
#include "stdint.h"
#include "stdlib.h"
#include "string.h"
#include "debug.h"
#ifndef LIST_DEFAULT_RESERVE
#define LIST_DEFAULT_RESERVE 4
#endif
List list_init(size_t element_size) {
List self = {
.element_size = element_size,
.cap = LIST_DEFAULT_RESERVE,
.len = 0,
.data = malloc(element_size * LIST_DEFAULT_RESERVE),
};
if(self.data == NULL) {
LOG_ERROR("Failed to allocate list with starting capacity of %d", LIST_DEFAULT_RESERVE);
self.cap = 0;
}
return self;
}
List list_copy(const List* source) {
List self = list_init(source->element_size);
list_reserve(&self, source->cap);
if(self.cap > 0) {
memcpy(self.data, source->data, source->element_size * source->len);
self.len = source->len;
} else {
LOG_ERROR("Failed to reserve space");
}
return self;
}
void list_empty(List* self) {
if(self->data == NULL || self->cap == 0)
return;
self->data = NULL;
self->cap = 0;
self->len = 0;
}
void list_reserve(List* self, size_t at_least) {
if(at_least < self->cap)
return;
size_t new_cap = self->cap > 0 ? self->cap : LIST_DEFAULT_RESERVE;
while(at_least >= new_cap) {
new_cap *= 2;
}
void* new;
if(self->data == NULL)
new = malloc(new_cap * self->element_size);
else
new = realloc(self->data, new_cap * self->element_size);
ASSERT_RETURN(new != NULL,, "Failed to reserve space for %zu extra elements in list", new_cap);
self->data = new;
self->cap = new_cap;
}
void* list_at_unchecked(List* self, size_t at) {
union {
uint8_t* as_byte;
void* as_void;
} data = {
.as_void = self->data
};
return data.as_byte + self->element_size * at;
}
void* list_at(List* self, size_t at) {
ASSERT_RETURN(at < self->len, NULL, "Index %zu out of bounds", at);
return list_at_unchecked(self, at);
}
size_t list_add(List* self, void* item) {
list_reserve(self, self->len + 1);
union {
uint8_t* as_byte;
void* as_void;
} data = {
.as_void = self->data
};
uint8_t* into = data.as_byte + (self->element_size * self->len);
memcpy(into, item, self->element_size);
++self->len;
return self->len - 1;
}
void list_insert(List* self, void* item, size_t at) {
list_reserve(self, self->len + 1);
if(at >= self->len) {
list_add(self, item);
return;
}
union {
uint8_t* as_byte;
void* as_void;
} data = {
.as_void = self->data
};
uint8_t* from = data.as_byte + (self->element_size * at);
uint8_t* into = data.as_byte + (self->element_size * (at + 1));
uint8_t* end = data.as_byte + (self->element_size * self->len);
memmove(into, from, end - from);
memcpy(from, item, self->element_size);
++self->len;
}
void list_erase(List* self, size_t at) {
ASSERT_RETURN(at < self->len,, "Index %zu out of bounds", at);
union {
uint8_t* as_byte;
void* as_void;
} data = {
.as_void = self->data
};
uint8_t* into = data.as_byte + at * self->element_size;
uint8_t* from = data.as_byte + (at + 1) * self->element_size;
if(at < self->len - 1)
memmove(into, from, (self->len - at) * self->element_size);
--self->len;
size_t new_cap = self->cap;
while(new_cap > self->len) {
new_cap /= 2;
}
new_cap *= 2;
if(new_cap == self->cap)
return;
void* shrunk = realloc(self->data, new_cap * self->element_size);
ASSERT_RETURN(shrunk != NULL || new_cap == 0,, "Failed to shrink List to %zu", new_cap);
self->data = shrunk;
self->cap = new_cap;
}
void* list_iterator_begin(List* self) {
return list_at_unchecked(self, 0);
}
void* list_iterator_end(List* self) {
return list_at_unchecked(self, self->len);
}
size_t list_contains(List* self, void* query) {
union {
uint8_t* as_byte;
void* as_void;
} data = {
.as_void = self->data
};
for(size_t i = 0; i < self->len; ++i) {
if(memcmp(data.as_byte + (i * self->element_size), query, self->element_size) == 0)
return i;
}
return self->len;
}

@ -1 +1 @@
Subproject commit 253cc0cb0c40524ae27b940e57d197a5c38c58d4
Subproject commit f84e3a3a27d626405173bd84055c299969cf7033

View file

@ -8,13 +8,13 @@
#include "sprite.h"
#include "variant.h"
START_REFLECT(Enemy)
REFLECT_TYPECLASS(Enemy, Transformable)
REFLECT_TYPECLASS(Enemy, Drop)
REFLECT_TYPECLASS(Enemy, PhysicsEntity)
REFLECT_TYPECLASS(Enemy, BehaviourEntity)
REFLECT_TYPECLASS(Enemy, Damagable)
END_REFLECT(Enemy)
START_REFLECT(Enemy);
REFLECT_TYPECLASS(Enemy, Transformable);
REFLECT_TYPECLASS(Enemy, Drop);
REFLECT_TYPECLASS(Enemy, PhysicsEntity);
REFLECT_TYPECLASS(Enemy, BehaviourEntity);
REFLECT_TYPECLASS(Enemy, Damagable);
END_REFLECT(Enemy);
impl_Transformable_for(Enemy,
EnemyGetTransform
@ -75,9 +75,9 @@ Enemy* MakeEnemy() {
sprite_set_origin(self->sprite, MakeVector(0.45f, 0.925f));
// load and configure animations
self->idleAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Idle.png", IVectorFrom(512)), 1.5f, LoopMode_Loop);
self->walkAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Walk.png", IVectorFrom(512)), 1.5f, LoopMode_Loop);
self->hurtAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Hurt.png", IVectorFrom(512)), 5.f, LoopMode_Stop);
self->idleAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Idle.png", IVectorFrom(512)), 1.5f, LoopMode_Loop, NULL, 0);
self->walkAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Walk.png", IVectorFrom(512)), 1.5f, LoopMode_Loop, NULL, 0);
self->hurtAnim = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Hurt.png", IVectorFrom(512)), 5.f, LoopMode_Stop, NULL, 0);
self->behaviour = state_machine_init(self, EnemyIdle());
return self;

View file

@ -18,7 +18,7 @@ void Internal_HurtboxDealDamage(const Hurtbox* self, List* colliders, float min_
}
}
int HurtboxCast(Hurtbox* self, float facing_dir) {
int HurtboxCast(Hurtbox* self, float facing_dir, List *out) {
const IPhysicsEntity* physics_entity = mirror_get_typeclass(self->owner.data, self->owner.mirror, "PhysicsEntity");
const ITransformable* transformable = mirror_get_typeclass(self->owner.data, self->owner.mirror, "Transformable");
@ -32,5 +32,9 @@ int HurtboxCast(Hurtbox* self, float facing_dir) {
const Vector offset = vaddf(transform->position, MakeVector(facing_dir * self->offset.x, self->offset.y));
List found = physics_world_box_query_all(offset, self->size, PHYSICS_LAYER_COMBAT, body);
Internal_HurtboxDealDamage(self, &found, transform->position.y - self->depth_extent, transform->position.y + self->depth_extent);
if(out == NULL)
list_empty(&found);
else
*out = found;
return found.len;
}

View file

@ -13,6 +13,6 @@ typedef struct Hurtbox {
float depth_extent;
} Hurtbox;
int HurtboxCast(Hurtbox* self, float facing_dir);
extern int HurtboxCast(Hurtbox* self, float facing_dir, List *out);
#endif // !FIGHT_HURTBOX_H

View file

@ -12,12 +12,12 @@
const Vector PLAYER_SPEED = { 1.0f, 0.50f };
static const float PLAYER_INPUT_RATE = 1.f/15.f;
START_REFLECT(Player)
REFLECT_TYPECLASS(Player, Drop)
REFLECT_TYPECLASS(Player, PhysicsEntity)
REFLECT_TYPECLASS(Player, BehaviourEntity)
REFLECT_TYPECLASS(Player, Transformable)
END_REFLECT(Player)
START_REFLECT(Player);
REFLECT_TYPECLASS(Player, Drop);
REFLECT_TYPECLASS(Player, PhysicsEntity);
REFLECT_TYPECLASS(Player, BehaviourEntity);
REFLECT_TYPECLASS(Player, Transformable);
END_REFLECT(Player);
impl_Drop_for(Player,
DestroyPlayer
@ -93,6 +93,7 @@ Player* MakePlayer() {
.slide = NULL,
.animationStateMachine = NULL,
.boxes = malloc(sizeof(Hurtbox) * 3),
.pushInputTimer = 0.f,
.inputLog = list_from_type(PlayerInputFrame),
@ -117,15 +118,15 @@ Player* MakePlayer() {
sprite_set_origin(self->sprite, MakeVector(0.45f, 0.925f));
// load and configure animations
self->idle = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Idle.png", IVectorFrom(512)), 1.5f, LoopMode_Loop);
self->walk = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Walk.png", IVectorFrom(512)), 5.f, LoopMode_Loop);
self->jump = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jumping.png", IVectorFrom(512)), 1.f, LoopMode_Stop);
self->jab_a = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jab_A.png", IVectorFrom(512)), 10.f, LoopMode_Stop);
self->jab_b = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jab_B.png", IVectorFrom(512)), 10.f, LoopMode_Stop);
self->kick_a = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Kick_A.png", IVectorFrom(512)), 12.f, LoopMode_Stop);
self->slash = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Slash.png", IVectorFrom(512)), 12.f, LoopMode_Stop);
self->air_heavy = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Air_Heavy.png", IVectorFrom(512)), 10.f, LoopMode_Stop);
self->slide = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Slide.png", IVectorFrom(512)), 1.f, LoopMode_Loop);
self->idle = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Idle.png", IVectorFrom(512)), 1.5f, LoopMode_Loop, NULL, 0);
self->walk = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Walk.png", IVectorFrom(512)), 5.f, LoopMode_Loop, NULL, 0);
self->jump = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jumping.png", IVectorFrom(512)), 1.f, LoopMode_Stop, NULL, 0);
self->jab_a = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jab_A.png", IVectorFrom(512)), 10.f, LoopMode_Stop, NULL, 0);
self->jab_b = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jab_B.png", IVectorFrom(512)), 10.f, LoopMode_Stop, NULL, 0);
self->kick_a = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Kick_A.png", IVectorFrom(512)), 12.f, LoopMode_Stop, NULL, 0);
self->slash = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Slash.png", IVectorFrom(512)), 12.f, LoopMode_Stop, NULL, 0);
self->air_heavy = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Air_Heavy.png", IVectorFrom(512)), 10.f, LoopMode_Stop, NULL, 0);
self->slide = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Slide.png", IVectorFrom(512)), 1.f, LoopMode_Loop, NULL, 0);
self->animationStateMachine = state_machine_init(self, PlayerIdle());

View file

@ -1,6 +1,7 @@
#ifndef FIGHT_PLAYER_H
#define FIGHT_PLAYER_H
#include "Hurtbox.h"
#include "dictionary.h"
#include "state_machine.h"
#include "mirror.h"
@ -56,9 +57,9 @@ typedef struct Player {
AnimationSprite* slide;
StateMachine* animationStateMachine;
Hurtbox *boxes;
AnimationSprite* currentAnimation;
float pushInputTimer;
List inputLog;
PlayerInputFrame nextInputFrame;

View file

@ -82,7 +82,7 @@ void PlayerHurtbox(Player* self, DamageEventData damage, Vector hitbox_size, Vec
.offset = vaddf(offset, MakeVector(0.f, self->height)),
.depth_extent = 0.15f,
};
HurtboxCast(&box, self->facing);
HurtboxCast(&box, self->facing, NULL);
}
void PlayerJabA_Enter(Player* self) {

View file

@ -4,11 +4,11 @@
#include "mirror.h"
#include "physics_world.h"
START_REFLECT(Prop)
REFLECT_TYPECLASS(Prop, Transformable)
REFLECT_TYPECLASS(Prop, Drop)
REFLECT_TYPECLASS(Prop, BehaviourEntity)
END_REFLECT(Prop)
START_REFLECT(Prop);
REFLECT_TYPECLASS(Prop, Transformable);
REFLECT_TYPECLASS(Prop, Drop);
REFLECT_TYPECLASS(Prop, BehaviourEntity);
END_REFLECT(Prop);
impl_Transformable_for(Prop,
PropGetTransform