('ent_miniworld', 'Mini World', '', 22 ),
('ent_prop', 'Prop', '', 23 ),
('ent_list', 'Entity List', '', 24 ),
- ('ent_region', 'Region', '', 25 )
+ ('ent_region', 'Region', '', 25 ),
+ ('ent_glider', 'Glider', '', 26 ),
]
-MDL_VERSION_NR = 104
+MDL_VERSION_NR = 105
SR_TRIGGERABLE = [ 'ent_audio', 'ent_ccmd', 'ent_gate', 'ent_challenge', \
'ent_relay', 'ent_skateshop', 'ent_objective', 'ent_route',\
- 'ent_miniworld', 'ent_region' ]
+ 'ent_miniworld', 'ent_region', 'ent_glider', 'ent_list' ]
def get_entity_enum_id( alias ):
#{
("reserved",vg_audio_clip)]
#}
+# NOTE: not really an entity. no reason for ent_ -- makes more sense as file_,
+# but then again, too late to change because compat.
class ent_audio_clip(Structure):
#{
_fields_ = [("_anon",union_file_audio_clip),
("probability",c_float)]
#}
+class ent_list(Structure):
+#{
+ _fields_ = [("entity_ref_start",c_uint32),
+ ("entity_ref_count",c_uint32)]
+#}
+
+# used in ent_list
+class file_entity_ref(Structure):
+#{
+ _fields_ = [("index",c_uint32)]
+#}
+
class ent_checkpoint(Structure):
#{
_fields_ = [("gate_index",c_uint16),
_fields_ = [("start",c_uint16),("count",c_uint16)]
#}
+class ent_glider(Structure):#{
+ _fields_ = [("transform",mdl_transform),
+ ("flags",c_uint32),
+ ("cooldown",c_float)]
+ sr_functions = { 0: 'unlock',
+ 1: 'equip' }
+#}
+
class ent_water(Structure):
#{
_fields_ = [("transform",mdl_transform),
("submesh_start",c_uint32), ("submesh_count",c_uint32),
("pstr_title",c_uint32),
("flags",c_uint32),
- ("zone_volume",c_uint32)]
+ ("zone_volume",c_uint32),
+ #105+
+ ("target0",c_uint32*2)]
sr_functions = { 0: 'enter', 1: 'leave' }
#}
#}
audio_clip_count = 0
+ entity_file_ref_count = 0
for ent_type, arr in sr_compile.entities.items():#{
print(F"[SR] Compiling {len(arr)} {ent_type}{'s' if len(arr)>1 else ''}")
sr_compile_mesh_internal( obj )
region.pstr_title = sr_compile_string( obj_data.title )
region.zone_volume = sr_entity_id( obj_data.zone_volume )
+ region.target0[0] = sr_entity_id( obj_data.target0 )
+ region.target0[1] = obj_data.target0_event
sr_ent_push( region )
#}
elif ent_type == 'ent_relay':#{
relay.targets[3][1] = obj_data.target3_event
sr_ent_push( relay )
#}
+ # elif ent_type == 'ent_list':#{
+ # lista = ent_list()
+ # obj_data = obj.SR_data.ent_list[0]
+
+ # lista.entity_ref_start = entity_file_ref_count
+ # lista.entity_ref_count = len( obj_data.entities )
+ # entity_file_ref_count += lista.entity_ref_count
+
+ # for child in obj_data.entities:#{
+ # reference_struct = file_entity_ref()
+ # reference_struct.index = sr_entity_id( child.target )
+ # sr_ent_push( reference_struct )
+ # #}
+
+ # sr_ent_push( lista )
+ # #}
+ elif ent_type == 'ent_glider':#{
+ glider = ent_glider()
+ compile_obj_transform( obj, glider.transform )
+ sr_ent_push( glider )
+ #}
elif ent_type == 'ent_cubemap':#{
cubemap = ent_cubemap()
co = obj.matrix_world @ Vector((0,0,0))
#}
#}
+class SR_OBJECT_ENT_GLIDER(bpy.types.PropertyGroup):#{
+ nothing: bpy.props.StringProperty()
+#}
class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):#{
subtype: bpy.props.EnumProperty(
zone_volume: bpy.props.PointerProperty(
type=bpy.types.Object, name="Zone Volume", \
poll=lambda self,obj: sr_filter_ent_type(obj,['ent_volume']))
+
+ target0: bpy.props.PointerProperty( \
+ type=bpy.types.Object, name="Triger on unlock", \
+ poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE))
+ target0_event: bpy.props.IntProperty( name="Event/Method" )
+
+ @staticmethod
+ def sr_inspector( layout, data ):#{
+ layout.prop( data[0], 'title' )
+ layout.prop( data[0], 'zone_volume' )
+ SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target0' )
+ #}
#}
class SR_OBJECT_ENT_RELAY(bpy.types.PropertyGroup):#{
ent_relay: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_RELAY)
ent_miniworld: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_MINIWORLD)
ent_list: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_LIST)
+ ent_glider: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_GLIDER)
ent_type: bpy.props.EnumProperty(
name="Type",
#}
#}
+def cv_draw_wireframe( mdl, points, colour ):#{
+ for i in range(len(points)//2):#{
+ p0 = mdl@points[i*2+0]
+ p1 = mdl@points[i*2+1]
+ cv_draw_line( p0, p1, colour )
+ #}
+#}
+
def cv_ent_gate( obj ):
#{
global cv_view_verts, cv_view_colours
#}
#}
#}
+ elif ent_type == 'ent_glider':#{
+ mesh = [Vector((-1.13982, 0.137084, -0.026358)), \
+ Vector(( 1.13982, 0.137084, -0.026358)), \
+ Vector(( 0.0, 1.6, 1.0)), \
+ Vector(( 0.0, -3.0, 1.0)), \
+ Vector(( -3.45, -1.78, 0.9)), \
+ Vector(( 0.0, 1.6, 1.0)), \
+ Vector(( 3.45, -1.78, 0.9)), \
+ Vector(( 0.0, 1.6, 1.0)), \
+ Vector(( 3.45, -1.78, 0.9)), \
+ Vector(( -3.45, -1.78, 0.9))]
+
+ cv_draw_wireframe( obj.matrix_world, mesh, (1,1,1) )
+ #}
elif ent_type == 'ent_skateshop':#{
data = obj.SR_data.ent_skateshop[0]
display = data.mark_display
if display1:
cv_draw_ucube(display1.matrix_world, cc1, display_cu, display_co)
#}
+ # elif ent_type == 'ent_list':#{
+ # data = obj.SR_data.ent_list[0]
+ # for child in data.entities:#{
+ # if child.target:#{
+ # cv_draw_arrow( obj.location, child.target.location, \
+ # (.5,.5,.5), 0.1 )
+ # #}
+ # #}
+ # #}
+ elif ent_type == 'ent_region':#{
+ data = obj.SR_data.ent_region[0]
+ if data.target0:#{
+ cv_draw_arrow( obj.location, data.target0.location, \
+ (.5,.5,.5), 0.1 )
+ #}
+ #}
elif ent_type == 'ent_menuitem':#{
for i,col in enumerate(obj.users_collection):#{
colour32 = hash_djb2( col.name )
SR_OBJECT_ENT_RELAY,SR_OBJECT_ENT_MINIWORLD,\
SR_OBJECT_ENT_LIST_ENTRY, SR_UL_ENT_LIST, SR_OBJECT_ENT_LIST, \
SR_OT_ENT_LIST_NEW_ITEM, SR_OT_ENT_LIST_DEL_ITEM,\
+ SR_OBJECT_ENT_GLIDER, \
\
SR_OBJECT_PROPERTIES, SR_LIGHT_PROPERTIES, SR_BONE_PROPERTIES,
SR_MESH_PROPERTIES, SR_MATERIAL_PROPERTIES \
--- /dev/null
+#pragma once
+#include "entity.h"
+#include "player_glide.h"
+
+static void ent_glider_call( world_instance *world, ent_call *call ){
+ u32 index = mdl_entity_id_id( call->id );
+ ent_glider *glider = mdl_arritm( &world->ent_glider, index );
+
+ if( call->function == 0 ){
+ glider->flags |= 0x1;
+ }
+ else if( call->function == 1 ){
+ if( glider->flags & 0x1 ){
+ player_glide_equip_glider();
+ }
+ }
+ else {
+ vg_print_backtrace();
+ vg_error( "Unhandled function id: %i\n", call->function );
+ }
+}
--- /dev/null
+#pragma once
+#include "entity.h"
+
+static void ent_glider_call( world_instance *world, ent_call *call );
region->flags = combined;
world_total &= combined;
+
+ /* run unlock triggers. v105+ */
+ if( world->meta.info.version >= 105 ){
+ if( region->flags & (k_ent_route_flag_achieve_gold|
+ k_ent_route_flag_achieve_silver) ){
+ if( region->target0[0] ){
+ ent_call call;
+ call.data = NULL;
+ call.id = region->target0[0];
+ call.function = region->target0[1];
+ entity_call( world, &call );
+ }
+ }
+ }
}
u32 instance_id = world - world_static.instances;
#include "ent_miniworld.c"
#include "ent_region.c"
#include "ent_traffic.c"
+#include "ent_glider.c"
typedef void (*fn_entity_call_handler)( world_instance *, ent_call *);
[k_ent_challenge] = ent_challenge_call,
[k_ent_route] = ent_route_call,
[k_ent_miniworld] = ent_miniworld_call,
- [k_ent_region] = ent_region_call
+ [k_ent_region] = ent_region_call,
+ [k_ent_glider] = ent_glider_call
};
if( type >= vg_list_size(table) ){
typedef struct ent_miniworld ent_miniworld;
typedef struct ent_prop ent_prop;
typedef struct ent_region ent_region;
+typedef struct ent_list ent_list;
+typedef struct ent_glider ent_glider;
enum entity_alias{
k_ent_none = 0,
k_ent_miniworld = 22,
k_ent_prop = 23,
k_ent_list = 24,
- k_ent_region = 25
+ k_ent_region = 25,
+ k_ent_glider = 26
};
static u32 mdl_entity_id_type( u32 entity_id ){
struct ent_region {
mdl_transform transform;
- u32 submesh_start, submesh_count, pstr_title, flags, zone_volume;
+ u32 submesh_start, submesh_count, pstr_title, flags, zone_volume,
+
+ /* 105+ */
+ target0[2];
+};
+
+struct ent_glider {
+ mdl_transform transform;
+ u32 flags;
+ f32 cooldown;
};
#include "world.h"
k_gui_icon_player,
k_gui_icon_rift_run_gold,
k_gui_icon_rift_run_silver,
+ k_gui_icon_glider,
k_gui_icon_count,
};
gui.icons[ k_gui_icon_rift_run_2d ] = gui_find_icon( "icon_rift_run2d" );
gui.icons[ k_gui_icon_friend ] = gui_find_icon( "icon_friend" );
gui.icons[ k_gui_icon_player ] = gui_find_icon( "icon_player" );
+ gui.icons[ k_gui_icon_glider ] = gui_find_icon( "icon_glider" );
gui.icons[ k_gui_icon_rift_run_gold ] =
gui_find_icon("icon_rift_run_medal_gold");
gui.icons[ k_gui_icon_rift_run_silver]=
#include "skaterift.h"
#define MDL_VERSION_MIN 101
-#define MDL_VERSION_NR 104
+#define MDL_VERSION_NR 105
enum mdl_shader{
k_shader_standard = 0,
player_glide.info_drag[2] );
}
+static void player_glide_equip_glider(void){
+ if( !localplayer.have_glider ){
+ localplayer.have_glider = 1;
+ localplayer.glider_orphan = 0;
+ player_glide.t = -1.0f;
+ }
+}
+
static int ccmd_player_glider_spawn( int argc, const char *argv[] ){
- localplayer.have_glider = 1;
- localplayer.glider_orphan = 0;
- player_glide.t = -1.0f;
+ if( vg_console.cheats ){
+ player_glide_equip_glider();
+ }
+ else {
+ vg_error( "Can't spawn without cheats enabled.\n" );
+ }
return 0;
}
m4x3f mmdl, enum board_shader shader );
static void
player_glide_remote_animator_exchange( bitpack_ctx *ctx, void *data );
+static void player_glide_equip_glider(void);
struct player_subsystem_interface static player_subsystem_glide = {
.pre_update = player_glide_pre_update,
rb_update_matrices( rb );
}
+ localplayer.subsystem = frame->system;
+
/* restore the seperated glider data if we have it */
if( frame->data_table[ k_replay_framedata_glider ][1] ){
- localplayer.subsystem = frame->system;
-
struct replay_glider_data *inf =
replay_frame_data( frame, k_replay_framedata_glider );
ent_cubemap,
ent_miniworld,
ent_prop,
- ent_region;
+ ent_region,
+ ent_glider;
enum skybox {
k_skybox_default,
#include "ent_skateshop.h"
#include "ent_route.h"
#include "ent_traffic.h"
+#include "ent_glider.h"
static void world_entity_focus( u32 entity_id ){
localplayer.immobile = 1;
{ k_ent_gate, &world->ent_gate },
{ k_ent_objective, &world->ent_objective },
{ k_ent_volume, &world->ent_volume },
- { k_ent_challenge, &world->ent_challenge }
+ { k_ent_challenge, &world->ent_challenge },
+ { k_ent_glider, &world->ent_glider }
};
for( u32 i=0; i<vg_list_size(indexables); i++ )
mdl_transform_m4x3( &challenge->transform, transform );
m4x3_expand_aabb_aabb( transform, bound, box );
}
+ else if( type == k_ent_glider ){
+ ent_glider *glider = mdl_arritm( &world->ent_glider, index );
+ m4x3f transform;
+ mdl_transform_m4x3( &glider->transform, transform );
+ m4x3_expand_aabb_aabb( transform, bound,
+ (boxf){{-1.0f,-1.0f,-1.0f},{ 1.0f, 1.0f, 1.0f}} );
+ }
else{
vg_fatal_error( "Programming error\n" );
}
ent_challenge *challenge = mdl_arritm( &world->ent_challenge, index );
return challenge->transform.co[axis];
}
+ else if( type == k_ent_glider ){
+ ent_glider *glider = mdl_arritm( &world->ent_glider, index );
+ return glider->transform.co[axis];
+ }
else {
vg_fatal_error( "Programming error\n" );
return INFINITY;
MDL_LOAD_ARRAY( meta, &world->ent_miniworld, ent_miniworld, heap );
MDL_LOAD_ARRAY( meta, &world->ent_prop, ent_prop, heap );
MDL_LOAD_ARRAY( meta, &world->ent_region, ent_region, heap );
+ MDL_LOAD_ARRAY( meta, &world->ent_glider, ent_glider, heap );
mdl_array_ptr infos;
MDL_LOAD_ARRAY( meta, &infos, ent_worldinfo, vg_mem.scratch );
respawn_map_draw_icon( cam, k_gui_icon_rift_run_2d,
route->board_transform[3] );
}
+
+ for( u32 i=0; i<mdl_arrcount(&world->ent_glider); i ++ ){
+ ent_glider *glider = mdl_arritm( &world->ent_glider, i );
+
+ v4f colour = { 1,1,1,1 };
+
+ if( !(glider->flags & 0x1) )
+ v3_muls( colour, 0.5f, colour );
+ gui_icon_setcolour( colour );
+
+ respawn_map_draw_icon( cam, k_gui_icon_glider, glider->transform.co );
+ }
}
static void world_map_enter(void){
#include "ent_miniworld.h"
#include "player_remote.h"
#include "ent_skateshop.h"
+#include "shaders/model_entity.h"
static int ccmd_set_time( int argc, const char *argv[] ){
world_instance *world = world_current_instance();
sizeof(struct ub_world_lighting), &world->ub_lighting );
}
+static void render_other_entities( world_instance *world, camera *cam ){
+ f32 radius = 40.0f;
+ bh_iter it;
+ bh_iter_init_range( 0, &it, cam->pos, radius+10.0f );
+
+ u32 glider_list[4],
+ glider_count = 0;
+
+ i32 idx;
+ while( bh_next( world->entity_bh, &it, &idx ) ){
+ u32 id = world->entity_list[ idx ],
+ type = mdl_entity_id_type( id ),
+ index = mdl_entity_id_id( id );
+
+ if( type == k_ent_glider ) {
+ if( glider_count < vg_list_size(glider_list) )
+ glider_list[ glider_count ++ ] = index;
+ }
+ }
+
+ shader_model_entity_use();
+ shader_model_entity_uTexMain( 0 );
+ shader_model_entity_uCamera( cam->transform[3] );
+ shader_model_entity_uPv( cam->mtx.pv );
+
+ WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_entity );
+
+ for( u32 j=0; j<glider_count; j ++ ){
+ ent_glider *glider = mdl_arritm( &world->ent_glider, glider_list[j] );
+
+ if( !(glider->flags & 0x1) )
+ continue;
+
+ m4x3f mdl;
+ mdl_transform_m4x3( &glider->transform, mdl );
+
+ f32 dist = v3_dist( glider->transform.co, cam->pos ) * (1.0f/radius),
+ scale = vg_smoothstepf( vg_clampf( 5.0f-dist*5.0f, 0.0f,1.0f ) );
+ m3x3_scalef( mdl, scale );
+
+ render_glider_model( cam, world, mdl, k_board_shader_entity );
+ }
+}
+
static void render_world( world_instance *world, camera *cam,
int stenciled, int viewing_from_gate,
int with_water, int with_cubemaps ){
}
render_remote_players( world, cam );
+ render_other_entities( world, cam );
ent_miniworld_render( world, cam );
if( stenciled ){