5 #include "world_load.h"
8 VG_STATIC
void world_gen_entities_init(void)
10 world_instance
*world
= world_loading_instance();
13 for( u32 j
=0; j
<mdl_arrcount(&world
->ent_light
); j
++ ){
14 ent_light
*light
= mdl_arritm( &world
->ent_light
, j
);
17 q_m3x3( light
->transform
.q
, to_world
);
18 v3_copy( light
->transform
.co
, to_world
[3] );
19 m4x3_invert_affine( to_world
, light
->inverse_world
);
21 light
->angle_sin_cos
[0] = sinf( light
->angle
* 0.5f
);
22 light
->angle_sin_cos
[1] = cosf( light
->angle
* 0.5f
);
26 for( u32 j
=0; j
<mdl_arrcount(&world
->ent_gate
); j
++ ){
27 ent_gate
*gate
= mdl_arritm( &world
->ent_gate
, j
);
29 if( gate
->type
== k_gate_type_teleport
){
30 gate_transform_update( gate
);
33 vg_async_call( world_link_nonlocal_async
, world
, 0 );
36 for( u32 j
=0; j
<mdl_arrcount(&world
->ent_water
); j
++ ){
37 ent_water
*water
= mdl_arritm( &world
->ent_water
, j
);
38 if( world
->water
.enabled
){
39 vg_warn( "Multiple water surfaces in level!\n" );
43 world
->water
.enabled
= 1;
44 water_set_surface( world
, water
->transform
.co
[1] );
48 for( u32 j
=0; j
<mdl_arrcount(&world
->ent_volume
); j
++ ){
49 ent_volume
*volume
= mdl_arritm( &world
->ent_volume
, j
);
50 mdl_transform_m4x3( &volume
->transform
, volume
->to_world
);
51 m4x3_invert_full( volume
->to_world
, volume
->to_local
);
55 for( u32 j
=0; j
<mdl_arrcount(&world
->ent_audio
); j
++ ){
56 ent_audio
*audio
= mdl_arritm( &world
->ent_audio
, j
);
58 for( u32 k
=0; k
<audio
->clip_count
; k
++ ){
59 ent_audio_clip
*clip
= mdl_arritm( &world
->ent_audio_clip
,
60 audio
->clip_start
+k
);
62 if( clip
->file
.pack_size
){
63 u32 size
= clip
->file
.pack_size
,
64 offset
= clip
->file
.pack_offset
;
66 /* embedded files are fine to clear the scratch buffer, only
67 * external audio uses it */
69 vg_linear_clear( vg_mem
.scratch
);
70 void *data
= vg_linear_alloc( vg_mem
.scratch
,
71 clip
->file
.pack_size
);
73 mdl_fread_pack_file( &world
->meta
, &clip
->file
, data
);
75 clip
->clip
.path
= NULL
;
76 clip
->clip
.flags
= audio
->flags
;
77 clip
->clip
.data
= data
;
78 clip
->clip
.size
= size
;
81 clip
->clip
.path
= mdl_pstr( &world
->meta
, clip
->file
.pstr_path
);
82 clip
->clip
.flags
= audio
->flags
;
83 clip
->clip
.data
= NULL
;
87 audio_clip_load( &clip
->clip
, world
->heap
);
93 ent_spawn
*world_find_closest_spawn( world_instance
*world
, v3f position
)
95 ent_spawn
*rp
= NULL
, *r
;
96 float min_dist
= INFINITY
;
98 for( u32 i
=0; i
<mdl_arrcount(&world
->ent_spawn
); i
++ ){
99 r
= mdl_arritm( &world
->ent_spawn
, i
);
100 float d
= v3_dist2( r
->transform
.co
, position
);
109 if( mdl_arrcount(&world
->ent_spawn
) ){
110 vg_warn( "Invalid distances to spawns.. defaulting to first one.\n" );
111 return mdl_arritm( &world
->ent_spawn
, 0 );
114 vg_error( "There are no spawns in the level!\n" );
122 ent_spawn
*world_find_spawn_by_name( world_instance
*world
, const char *name
)
124 ent_spawn
*rp
= NULL
, *r
;
125 for( u32 i
=0; i
<mdl_arrcount(&world
->ent_spawn
); i
++ ){
126 r
= mdl_arritm( &world
->ent_spawn
, i
);
127 if( !strcmp( mdl_pstr(&world
->meta
, r
->pstr_name
), name
) ){
134 vg_warn( "No spawn named '%s'\n", name
);
139 VG_STATIC
void ent_volume_call( world_instance
*world
, ent_call
*call
)
141 u32 index
= mdl_entity_id_id( call
->id
);
142 ent_volume
*volume
= mdl_arritm( &world
->ent_volume
, index
);
143 if( !volume
->target
) return;
145 if( call
->function
== k_ent_function_trigger
){
146 call
->id
= volume
->target
;
148 if( volume
->type
== k_volume_subtype_particle
){
149 float *co
= alloca( sizeof(float)*3 );
150 co
[0] = vg_randf64()*2.0f
-1.0f
;
151 co
[1] = vg_randf64()*2.0f
-1.0f
;
152 co
[2] = vg_randf64()*2.0f
-1.0f
;
153 m4x3_mulv( volume
->to_world
, co
, co
);
155 call
->function
= k_ent_function_particle_spawn
;
157 entity_call( world
, call
);
160 entity_call( world
, call
);
165 VG_STATIC
void ent_audio_call( world_instance
*world
, ent_call
*call
){
166 if( world
->status
== k_world_status_unloading
){
167 vg_warn( "cannot modify audio while unloading world\n" );
171 u8 world_id
= (world
- world_static
.worlds
) + 1;
172 u32 index
= mdl_entity_id_id( call
->id
);
173 ent_audio
*audio
= mdl_arritm( &world
->ent_audio
, index
);
177 if( call
->function
== k_ent_function_particle_spawn
){
178 v3_copy( call
->data
, sound_co
);
180 else if( call
->function
== k_ent_function_trigger
){
181 v3_copy( audio
->transform
.co
, sound_co
);
184 vg_fatal_error( "ent_audio_call (invalid function id)" );
186 float chance
= vg_randf64()*100.0f
,
189 for( u32 i
=0; i
<audio
->clip_count
; i
++ ){
190 ent_audio_clip
*clip
= mdl_arritm( &world
->ent_audio_clip
,
191 audio
->clip_start
+i
);
193 float mod
= world
->probabilities
[ audio
->probability_curve
],
194 p
= clip
->probability
* mod
;
200 if( audio
->behaviour
== k_channel_behaviour_unlimited
){
201 audio_oneshot_3d( &clip
->clip
, sound_co
,
202 audio
->transform
.s
[0],
205 else if( audio
->behaviour
== k_channel_behaviour_discard_if_full
){
207 audio_get_group_idle_channel( audio
->group
,
208 audio
->max_channels
);
211 audio_channel_init( ch
, &clip
->clip
, audio
->flags
);
212 audio_channel_group( ch
, audio
->group
);
213 audio_channel_world( ch
, world_id
);
214 audio_channel_set_spacial( ch
, sound_co
, audio
->transform
.s
[0] );
215 audio_channel_edit_volume( ch
, audio
->volume
, 1 );
216 ch
= audio_relinquish_channel( ch
);
219 else if( audio
->behaviour
== k_channel_behaviour_crossfade_if_full
){
221 audio_get_group_idle_channel( audio
->group
,
222 audio
->max_channels
);
226 audio_channel
*existing
=
227 audio_get_group_first_active_channel( audio
->group
);
230 if( existing
->source
== &clip
->clip
){
236 existing
= audio_channel_fadeout(existing
, audio
->crossfade
);
239 ch
= audio_get_first_idle_channel();
243 audio_channel_init( ch
, &clip
->clip
, audio
->flags
);
244 audio_channel_group( ch
, audio
->group
);
245 audio_channel_world( ch
, world_id
);
246 audio_channel_fadein( ch
, audio
->crossfade
);
247 ch
= audio_relinquish_channel( ch
);
258 VG_STATIC
void ent_ccmd_call( world_instance
*world
, ent_call
*call
){
259 if( call
->function
== k_ent_function_trigger
){
260 u32 index
= mdl_entity_id_id( call
->id
);
261 ent_ccmd
*ccmd
= mdl_arritm( &world
->ent_ccmd
, index
);
262 vg_execute_console_input( mdl_pstr(&world
->meta
, ccmd
->pstr_command
) );
266 #endif /* WORLD_ENTITY_C */