3 #ifndef WORLD_LOGIC_BRICKS_H
4 #define WORLD_LOGIC_BRICKS_H
10 typedef struct logic_packet logic_packet
;
13 u32 location
, function
;
14 union mdl_128bit_union data
;
15 enum mdl_128bit_datatype type
;
18 VG_STATIC
void logic_bricks_debug_connection( world_instance
*world
,
19 mdl_node
*from
, u32 next
,
25 mdl_node
*to
= mdl_node_from_id( world
->meta
, next
);
28 float brightness
= 0.8f
+ world
->logic_bricks
[ from
->sub_uid
].usage
* 4.0f
;
29 v3_muls( colour
, brightness
, c
);
31 u32 clamped
= 0xff000000;
33 for( int i
=0; i
<3; i
++ )
35 u8 byte
= vg_minf( 1.0f
, c
[i
] ) * 255.0f
;
36 clamped
|= byte
<< (i
*8);
39 vg_line( from
->co
, to
->co
, clamped
);
42 VG_STATIC
void logic_bricks_debug( world_instance
*world
, v3f pos
)
44 v3f white
= {1.0f
,1.0f
,1.0f
},
45 red
= {1.0f
,0.2f
,0.1f
},
46 black
= {0.2f
,0.2f
,0.2f
};
50 for( int i
=0; i
<world
->logic_brick_count
; i
++ )
52 struct logic_brick_ref
*ref
= &world
->logic_bricks
[i
];
53 mdl_node
*node
= ref
->node
;
55 if( v3_dist2( node
->co
, pos
) > 50.0f
*50.0f
)
58 void *entdata
= mdl_get_entdata( world
->meta
, node
);
60 if( ref
->node
->classtype
== k_classtype_logic_wire
)
62 struct classtype_logic_wire
*wire
= entdata
;
64 logic_bricks_debug_connection( world
, node
, wire
->next
, white
);
66 else if( ref
->node
->classtype
== k_classtype_logic_chances
)
68 struct classtype_logic_chances
*chances
= entdata
;
70 logic_bricks_debug_connection(world
, node
, chances
->targets
[0], red
);
71 logic_bricks_debug_connection(world
, node
, chances
->targets
[1], black
);
73 else if( ref
->node
->classtype
== k_classtype_signal_splitter
)
75 struct classtype_signal_splitter
*splitter
= entdata
;
76 logic_bricks_debug_connection( world
, node
, splitter
->next
[0], white
);
77 logic_bricks_debug_connection( world
, node
, splitter
->next
[1], white
);
78 logic_bricks_debug_connection( world
, node
, splitter
->next
[2], white
);
79 logic_bricks_debug_connection( world
, node
, splitter
->next
[3], white
);
81 else if( ref
->node
->classtype
== k_classtype_soundscape
)
83 struct classtype_soundscape
*inf
= entdata
;
84 struct soundscape
*s
= &world
->soundscapes
[ ref
->internal_id
];
87 v3_copy( ref
->node
->co
, co
);
90 box
[0][0] = co
[0]-0.12f
;
91 box
[0][1] = co
[1]-0.12f
;
92 box
[0][2] = co
[2]-0.12f
;
93 box
[1][0] = co
[0]+0.12f
;
94 box
[1][1] = co
[1]+0.12f
+ 0.1f
*(float)inf
->max_instances
;
95 box
[1][2] = co
[2]+0.12f
;
97 vg_line_boxf( box
, VG__WHITE
);
99 for( int i
=0; i
<s
->usage_count
; i
++ )
101 vg_line_pt3( co
, 0.09f
, VG__GREEN
);
105 else if( ref
->node
->classtype
== k_classtype_trigger
)
107 struct classtype_trigger
*trigger
= entdata
;
108 logic_bricks_debug_connection( world
, node
, trigger
->target
, white
);
110 else if( ref
->node
->classtype
== k_classtype_particle_box
)
112 struct classtype_particle_box
*pb
= entdata
;
113 logic_bricks_debug_connection( world
, node
, pb
->target
, white
);
116 ref
->usage
*= vg_maxf( 0.0f
, 1.0f
-vg
.time_delta
*5.0f
);
120 VG_STATIC
void logic_packet_terminate( logic_packet
*packet
)
122 packet
->location
= 0xffffffff;
125 VG_STATIC
void logic_wire_call( world_instance
*world
,
126 struct logic_brick_ref
*ref
,
127 logic_packet
*packet
)
129 struct classtype_logic_wire
*inf
= mdl_get_entdata( world
->meta
, ref
->node
);
131 if( packet
->function
== 0 ) /* pass onwards */
135 if( inf
->data_type
!= k_mdl_128bit_datatype_nothing
)
137 packet
->data
= inf
->data
;
138 packet
->type
= inf
->data_type
;
141 mdl_node
*next
= mdl_node_from_id( world
->meta
, inf
->next
);
142 packet
->location
= next
->sub_uid
;
143 packet
->function
= inf
->function
;
146 logic_packet_terminate( packet
);
148 else if( packet
->function
== 1 ) /* TODO enable */
150 logic_packet_terminate( packet
);
152 else if( packet
->function
== 2 ) /* TODO disable */
154 logic_packet_terminate( packet
);
158 vg_error( "[INVALID FUNCTION] logic_wire:[%u]\n", packet
->function
);
159 logic_packet_terminate( packet
);
163 VG_STATIC
void logic_chances_call( world_instance
*world
,
164 struct logic_brick_ref
*ref
,
165 logic_packet
*packet
)
167 struct classtype_logic_chances
*inf
=
168 mdl_get_entdata( world
->meta
, ref
->node
);
170 if( packet
->function
== 0 ) /* pass along */
174 if( vg_randf() > inf
->p
)
177 if( inf
->targets
[red
] )
179 mdl_node
*pnext
= mdl_node_from_id( world
->meta
, inf
->targets
[red
] );
181 if( (pnext
->classtype
== k_classtype_logic_wire
) ||
182 (pnext
->classtype
== k_classtype_logic_chances
) ||
183 (pnext
->classtype
== k_classtype_signal_splitter
) )
185 packet
->location
= pnext
->sub_uid
;
189 vg_error( "[INVALID TARGET] logic_chances:pass( ... )\n" );
190 vg_warn( " target[%d] must be classtype logic_wire\n", red
);
191 logic_packet_terminate( packet
);
196 logic_packet_terminate( packet
);
199 else if( packet
->function
== 1 ) /* set ratio */
201 if( packet
->type
== k_mdl_128bit_datatype_number
)
203 inf
->p
= packet
->data
._f32
;
207 vg_error( "[INVALID ARGUMENT] logic_chances:set_ratio( f32 p )\n" );
210 logic_packet_terminate( packet
);
214 vg_error( "[INVALID FUNCTION] logic_chances:[%u]\n", packet
->function
);
215 logic_packet_terminate( packet
);
219 VG_STATIC
void logic_soundscape_call( world_instance
*world
,
220 struct logic_brick_ref
*ref
,
221 logic_packet
*packet
)
223 struct classtype_soundscape
*inf
= mdl_get_entdata( world
->meta
, ref
->node
);
224 struct soundscape
*soundscape
= &world
->soundscapes
[ ref
->internal_id
];
226 if( packet
->function
== 0 ) /* play */
228 /* TODO: Only spawn within certain range of player */
230 if( packet
->type
!= k_mdl_128bit_datatype_target
)
232 vg_error( "[INVALID ARGUMENT] logic_soundscape:play( ref sound )\n" );
233 vg_warn( " got datatype: %u\n", packet
->type
);
234 logic_packet_terminate( packet
);
238 mdl_node
*data
= mdl_node_from_id( world
->meta
, packet
->data
._u32
);
240 if( data
->classtype
!= k_classtype_audio
)
242 vg_error( "[INVALID TARGET] logic_soundscape:play( ref sound )\n" );
243 logic_packet_terminate( packet
);
247 if( soundscape
->usage_count
< soundscape
->max_instances
)
249 struct world_audio_thing
*audio
= &world
->audio_things
[data
->sub_uid
];
252 for( int i
=0; i
<soundscape
->max_instances
; i
++ )
254 if( !soundscape
->channels
[i
] )
257 soundscape
->channels
[i
] = audio_request_channel(
258 &audio
->temp_embedded_clip
,
261 if( soundscape
->channels
[i
] )
263 if( audio
->flags
& AUDIO_FLAG_SPACIAL_3D
)
265 audio_channel_set_spacial( soundscape
->channels
[i
],
266 soundscape
->spawn_position
,
270 audio_channel_edit_volume( soundscape
->channels
[i
],
277 soundscape
->usage_count
++;
284 logic_packet_terminate( packet
);
286 else if( packet
->function
== 1 ) /* set position */
288 if( packet
->type
!= k_mdl_128bit_datatype_vec3
)
290 vg_error( "[INVALID ARGUMENT] logic_soundscape:position( v3f co )\n" );
291 logic_packet_terminate( packet
);
295 v3_copy( packet
->data
._v4f
, soundscape
->spawn_position
);
296 logic_packet_terminate( packet
);
300 vg_error( "[INVALID FUNCTION] logic_wire:[%u]\n", packet
->function
);
301 logic_packet_terminate( packet
);
305 VG_STATIC
void _logic_trigger_base_call( world_instance
*world
, u32 target
,
306 logic_packet
*packet
)
308 if( packet
->function
== 0 ) /* pass onwards */
312 mdl_node
*next
= mdl_node_from_id( world
->meta
, target
);
313 packet
->location
= next
->sub_uid
;
314 packet
->function
= 0; /* always call the default function */
317 logic_packet_terminate( packet
);
321 vg_error( "[INVALID FUNCTION] logic_trigger:[%u]\n", packet
->function
);
322 logic_packet_terminate( packet
);
326 VG_STATIC
void logic_trigger_call( world_instance
*world
,
327 struct logic_brick_ref
*ref
,
328 logic_packet
*packet
)
330 struct classtype_trigger
*inf
= mdl_get_entdata( world
->meta
, ref
->node
);
331 _logic_trigger_base_call( world
, inf
->target
, packet
);
334 VG_STATIC
void logic_particle_call( world_instance
*world
,
335 struct logic_brick_ref
*ref
,
336 logic_packet
*packet
)
338 struct classtype_particle_box
*inf
=
339 mdl_get_entdata( world
->meta
, ref
->node
);
341 /* rate of 1.0 means we get one a second or 0.1 per tick */
343 if( vg_randf() < inf
->rate
* 0.1f
)
346 _logic_trigger_base_call( world
, inf
->target
, packet
);
350 logic_packet_terminate( packet
);
354 VG_STATIC
void logic_bricks_send_packet( world_instance
*world
,
355 logic_packet
*packet
);
357 VG_STATIC
void logic_splitter( world_instance
*world
,
358 struct logic_brick_ref
*ref
,
359 logic_packet
*packet
)
361 struct classtype_signal_splitter
*inf
362 = mdl_get_entdata( world
->meta
, ref
->node
);
364 if( packet
->function
== 0 ) /* pass onwards */
366 for( int i
=0; i
<4; i
++ )
370 logic_packet copy
= *packet
;
372 mdl_node
*next
= mdl_node_from_id( world
->meta
, inf
->next
[i
] );
373 copy
.location
= next
->sub_uid
;
374 copy
.function
= 0; /* always call the default function */
376 logic_bricks_send_packet( world
, ©
);
380 logic_packet_terminate( packet
);
384 vg_error( "[INVALID FUNCTION] logic_splitter:[%u]\n", packet
->function
);
385 logic_packet_terminate( packet
);
389 VG_STATIC
void logic_bricks_send_packet( world_instance
*world
,
390 logic_packet
*packet
)
392 while( packet
->location
!= 0xffffffff )
394 struct logic_brick_ref
*ref
= &world
->logic_bricks
[ packet
->location
];
395 enum classtype type
= ref
->node
->classtype
;
397 if( type
== k_classtype_logic_wire
)
399 logic_wire_call( world
, ref
, packet
);
401 else if( type
== k_classtype_logic_chances
)
403 logic_chances_call( world
, ref
, packet
);
405 else if( type
== k_classtype_soundscape
)
407 logic_soundscape_call( world
, ref
, packet
);
409 else if( type
== k_classtype_trigger
)
411 logic_trigger_call( world
, ref
, packet
);
413 else if( type
== k_classtype_particle_box
)
415 logic_particle_call( world
, ref
, packet
);
418 else if( type
== k_classtype_signal_splitter
)
420 logic_splitter( world
, ref
, packet
);
424 vg_error( "Undefined logic brick (entity type %d)\n", type
);
425 logic_packet_terminate( packet
);
432 VG_STATIC
void logic_bricks_world_gen_allocate( world_instance
*world
)
434 /* REVISION: unify allocations, loaders and extensions for entities.
435 * we currently seem to do every which entity a different way */
437 world
->logic_brick_count
= 0;
438 world
->logic_bricks
= NULL
;
439 world
->soundscape_count
= 0;
440 world
->trigger_count
= 0;
442 for( int i
=0; i
<world
->meta
->info
.node_count
; i
++ )
444 mdl_node
*pnode
= mdl_node_from_id( world
->meta
, i
);
446 if( pnode
->classtype
== k_classtype_logic_wire
||
447 pnode
->classtype
== k_classtype_logic_chances
||
448 pnode
->classtype
== k_classtype_soundscape
||
449 pnode
->classtype
== k_classtype_trigger
||
450 pnode
->classtype
== k_classtype_particle_box
||
451 pnode
->classtype
== k_classtype_signal_splitter
)
453 world
->logic_bricks
=
454 vg_linear_extend( world_global
.generic_heap
,
456 sizeof( struct logic_brick_ref
) );
458 pnode
->sub_uid
= world
->logic_brick_count
;
460 struct logic_brick_ref
*ref
=
461 &world
->logic_bricks
[ world
->logic_brick_count
];
463 ref
->internal_id
= 0;
465 if( pnode
->classtype
== k_classtype_soundscape
)
467 u32 id
= world
->soundscape_count
;
469 struct soundscape
*soundscape
= &world
->soundscapes
[ id
];
471 struct classtype_soundscape
*inf
=
472 mdl_get_entdata( world
->meta
, pnode
);
474 soundscape
->label
= mdl_pstr( world
->meta
, inf
->label
);
475 soundscape
->max_instances
= inf
->max_instances
;
476 soundscape
->allow_transitions
= inf
->allow_transitions
;
477 soundscape
->transition_duration
= inf
->transition_duration
;
478 v3_copy( pnode
->co
, soundscape
->spawn_position
);
480 ref
->internal_id
= id
;
481 world
->soundscape_count
++;
483 else if( pnode
->classtype
== k_classtype_trigger
||
484 pnode
->classtype
== k_classtype_particle_box
)
486 u32 id
= world
->trigger_count
;
487 struct trigger_zone
*trigger
= &world
->triggers
[ id
];
489 mdl_node_transform( pnode
, trigger
->transform
);
490 m4x3_invert_full( trigger
->transform
, trigger
->inv_transform
);
491 trigger
->target_logic_brick
= world
->logic_brick_count
;
492 trigger
->classtype
= pnode
->classtype
;
494 world
->trigger_count
++;
497 world
->logic_brick_count
++;
508 #endif /* WORLD_LOGIC_BRICKS_H */