3 #ifndef WORLD_LOGIC_BRICKS_H
4 #define WORLD_LOGIC_BRICKS_H
8 typedef struct logic_packet logic_packet
;
11 u32 location
, function
;
12 union mdl_128bit_union data
;
13 enum mdl_128bit_datatype type
;
16 VG_STATIC
void logic_bricks_debug_connection( world_instance
*world
,
17 mdl_node
*from
, u32 next
,
23 mdl_node
*to
= mdl_node_from_id( world
->meta
, next
);
26 float brightness
= 0.8f
+ world
->logic_bricks
[ from
->sub_uid
].usage
* 4.0f
;
27 v3_muls( colour
, brightness
, c
);
29 u32 clamped
= 0xff000000;
31 for( int i
=0; i
<3; i
++ )
33 u8 byte
= vg_minf( 1.0f
, c
[i
] ) * 255.0f
;
34 clamped
|= byte
<< (i
*8);
37 vg_line( from
->co
, to
->co
, clamped
);
40 VG_STATIC
void logic_bricks_debug( world_instance
*world
)
42 v3f white
= {1.0f
,1.0f
,1.0f
},
43 red
= {1.0f
,0.2f
,0.1f
},
44 black
= {0.2f
,0.2f
,0.2f
};
48 for( int i
=0; i
<world
->logic_brick_count
; i
++ )
50 struct logic_brick_ref
*ref
= &world
->logic_bricks
[i
];
51 mdl_node
*node
= ref
->node
;
53 void *entdata
= mdl_get_entdata( world
->meta
, node
);
55 if( ref
->node
->classtype
== k_classtype_logic_wire
)
57 struct classtype_logic_wire
*wire
= entdata
;
59 logic_bricks_debug_connection( world
, node
, wire
->next
, white
);
61 else if( ref
->node
->classtype
== k_classtype_logic_chances
)
63 struct classtype_logic_chances
*chances
= entdata
;
65 logic_bricks_debug_connection(world
, node
, chances
->targets
[0], red
);
66 logic_bricks_debug_connection(world
, node
, chances
->targets
[1], black
);
68 else if( ref
->node
->classtype
== k_classtype_signal_splitter
)
70 struct classtype_signal_splitter
*splitter
= entdata
;
71 logic_bricks_debug_connection( world
, node
, splitter
->next
[0], white
);
72 logic_bricks_debug_connection( world
, node
, splitter
->next
[1], white
);
73 logic_bricks_debug_connection( world
, node
, splitter
->next
[2], white
);
74 logic_bricks_debug_connection( world
, node
, splitter
->next
[3], white
);
76 else if( ref
->node
->classtype
== k_classtype_soundscape
)
78 struct classtype_soundscape
*inf
= entdata
;
79 struct soundscape
*s
= &world
->soundscapes
[ ref
->internal_id
];
82 v3_copy( ref
->node
->co
, co
);
85 box
[0][0] = co
[0]-0.12f
;
86 box
[0][1] = co
[1]-0.12f
;
87 box
[0][2] = co
[2]-0.12f
;
88 box
[1][0] = co
[0]+0.12f
;
89 box
[1][1] = co
[1]+0.12f
+ 0.1f
*(float)inf
->max_instances
;
90 box
[1][2] = co
[2]+0.12f
;
92 vg_line_boxf( box
, VG__WHITE
);
94 for( int i
=0; i
<s
->usage_count
; i
++ )
96 vg_line_pt3( co
, 0.09f
, VG__GREEN
);
100 else if( ref
->node
->classtype
== k_classtype_trigger
)
102 struct classtype_trigger
*trigger
= entdata
;
103 logic_bricks_debug_connection( world
, node
, trigger
->target
, white
);
105 else if( ref
->node
->classtype
== k_classtype_particle_box
)
107 struct classtype_particle_box
*pb
= entdata
;
108 logic_bricks_debug_connection( world
, node
, pb
->target
, white
);
111 ref
->usage
*= vg_maxf( 0.0f
, 1.0f
-vg
.time_delta
*5.0f
);
115 VG_STATIC
void logic_packet_terminate( logic_packet
*packet
)
117 packet
->location
= 0xffffffff;
120 VG_STATIC
void logic_wire_call( world_instance
*world
,
121 struct logic_brick_ref
*ref
,
122 logic_packet
*packet
)
124 struct classtype_logic_wire
*inf
= mdl_get_entdata( world
->meta
, ref
->node
);
126 if( packet
->function
== 0 ) /* pass onwards */
130 if( inf
->data_type
!= k_mdl_128bit_datatype_nothing
)
132 packet
->data
= inf
->data
;
133 packet
->type
= inf
->data_type
;
136 mdl_node
*next
= mdl_node_from_id( world
->meta
, inf
->next
);
137 packet
->location
= next
->sub_uid
;
138 packet
->function
= inf
->function
;
141 logic_packet_terminate( packet
);
143 else if( packet
->function
== 1 ) /* TODO enable */
145 logic_packet_terminate( packet
);
147 else if( packet
->function
== 2 ) /* TODO disable */
149 logic_packet_terminate( packet
);
153 vg_error( "[INVALID FUNCTION] logic_wire:[%u]\n", packet
->function
);
154 logic_packet_terminate( packet
);
158 VG_STATIC
void logic_chances_call( world_instance
*world
,
159 struct logic_brick_ref
*ref
,
160 logic_packet
*packet
)
162 struct classtype_logic_chances
*inf
=
163 mdl_get_entdata( world
->meta
, ref
->node
);
165 if( packet
->function
== 0 ) /* pass along */
169 if( vg_randf() > inf
->p
)
172 if( inf
->targets
[red
] )
174 mdl_node
*pnext
= mdl_node_from_id( world
->meta
, inf
->targets
[red
] );
176 if( pnext
->classtype
== k_classtype_logic_wire
)
178 packet
->location
= pnext
->sub_uid
;
182 vg_error( "[INVALID TARGET] logic_chances:pass( ... )\n" );
183 vg_warn( " target[%d] must be classtype logic_wire\n", red
);
184 logic_packet_terminate( packet
);
189 logic_packet_terminate( packet
);
192 else if( packet
->function
== 1 ) /* set ratio */
194 if( packet
->type
== k_mdl_128bit_datatype_number
)
196 inf
->p
= packet
->data
._f32
;
200 vg_error( "[INVALID ARGUMENT] logic_chances:set_ratio( f32 p )\n" );
203 logic_packet_terminate( packet
);
207 vg_error( "[INVALID FUNCTION] logic_chances:[%u]\n", packet
->function
);
208 logic_packet_terminate( packet
);
212 VG_STATIC
void logic_soundscape_call( world_instance
*world
,
213 struct logic_brick_ref
*ref
,
214 logic_packet
*packet
)
216 struct classtype_soundscape
*inf
= mdl_get_entdata( world
->meta
, ref
->node
);
217 struct soundscape
*soundscape
= &world
->soundscapes
[ ref
->internal_id
];
219 if( packet
->function
== 0 ) /* play */
221 /* TODO: Only spawn within certain range of player */
223 if( packet
->type
!= k_mdl_128bit_datatype_target
)
225 vg_error( "[INVALID ARGUMENT] logic_soundscape:play( ref sound )\n" );
226 vg_warn( " got datatype: %u\n", packet
->type
);
227 logic_packet_terminate( packet
);
231 mdl_node
*data
= mdl_node_from_id( world
->meta
, packet
->data
._u32
);
233 if( data
->classtype
!= k_classtype_audio
)
235 vg_error( "[INVALID TARGET] logic_soundscape:play( ref sound )\n" );
236 logic_packet_terminate( packet
);
240 if( soundscape
->usage_count
< soundscape
->max_instances
)
242 struct world_audio_thing
*audio
= &world
->audio_things
[data
->sub_uid
];
245 for( int i
=0; i
<soundscape
->max_instances
; i
++ )
247 if( !soundscape
->channels
[i
] )
250 soundscape
->channels
[i
] = audio_request_channel(
251 &audio
->temp_embedded_clip
,
254 if( soundscape
->channels
[i
] )
256 if( audio
->flags
& AUDIO_FLAG_SPACIAL_3D
)
258 audio_channel_set_spacial( soundscape
->channels
[i
],
259 soundscape
->spawn_position
,
263 audio_channel_edit_volume( soundscape
->channels
[i
],
270 soundscape
->usage_count
++;
277 logic_packet_terminate( packet
);
279 else if( packet
->function
== 1 ) /* set position */
281 if( packet
->type
!= k_mdl_128bit_datatype_vec3
)
283 vg_error( "[INVALID ARGUMENT] logic_soundscape:position( v3f co )\n" );
284 logic_packet_terminate( packet
);
288 v3_copy( packet
->data
._v4f
, soundscape
->spawn_position
);
289 logic_packet_terminate( packet
);
293 vg_error( "[INVALID FUNCTION] logic_wire:[%u]\n", packet
->function
);
294 logic_packet_terminate( packet
);
298 VG_STATIC
void _logic_trigger_base_call( world_instance
*world
, u32 target
,
299 logic_packet
*packet
)
301 if( packet
->function
== 0 ) /* pass onwards */
305 mdl_node
*next
= mdl_node_from_id( world
->meta
, target
);
306 packet
->location
= next
->sub_uid
;
307 packet
->function
= 0; /* always call the default function */
310 logic_packet_terminate( packet
);
314 vg_error( "[INVALID FUNCTION] logic_trigger:[%u]\n", packet
->function
);
315 logic_packet_terminate( packet
);
319 VG_STATIC
void logic_trigger_call( world_instance
*world
,
320 struct logic_brick_ref
*ref
,
321 logic_packet
*packet
)
323 struct classtype_trigger
*inf
= mdl_get_entdata( world
->meta
, ref
->node
);
324 _logic_trigger_base_call( world
, inf
->target
, packet
);
327 VG_STATIC
void logic_particle_call( world_instance
*world
,
328 struct logic_brick_ref
*ref
,
329 logic_packet
*packet
)
331 struct classtype_particle_box
*inf
=
332 mdl_get_entdata( world
->meta
, ref
->node
);
334 /* rate of 1.0 means we get one a second or 0.1 per tick */
336 if( vg_randf() < inf
->rate
* 0.1f
)
339 _logic_trigger_base_call( world
, inf
->target
, packet
);
343 logic_packet_terminate( packet
);
347 VG_STATIC
void logic_bricks_send_packet( world_instance
*world
,
348 logic_packet
*packet
);
350 VG_STATIC
void logic_splitter( world_instance
*world
,
351 struct logic_brick_ref
*ref
,
352 logic_packet
*packet
)
354 struct classtype_signal_splitter
*inf
355 = mdl_get_entdata( world
->meta
, ref
->node
);
357 if( packet
->function
== 0 ) /* pass onwards */
359 for( int i
=0; i
<4; i
++ )
363 logic_packet copy
= *packet
;
365 mdl_node
*next
= mdl_node_from_id( world
->meta
, inf
->next
[i
] );
366 copy
.location
= next
->sub_uid
;
367 copy
.function
= 0; /* always call the default function */
369 logic_bricks_send_packet( world
, ©
);
373 logic_packet_terminate( packet
);
377 vg_error( "[INVALID FUNCTION] logic_splitter:[%u]\n", packet
->function
);
378 logic_packet_terminate( packet
);
382 VG_STATIC
void logic_bricks_send_packet( world_instance
*world
,
383 logic_packet
*packet
)
385 while( packet
->location
!= 0xffffffff )
387 struct logic_brick_ref
*ref
= &world
->logic_bricks
[ packet
->location
];
388 enum classtype type
= ref
->node
->classtype
;
390 if( type
== k_classtype_logic_wire
)
392 logic_wire_call( world
, ref
, packet
);
394 else if( type
== k_classtype_logic_chances
)
396 logic_chances_call( world
, ref
, packet
);
398 else if( type
== k_classtype_soundscape
)
400 logic_soundscape_call( world
, ref
, packet
);
402 else if( type
== k_classtype_trigger
)
404 logic_trigger_call( world
, ref
, packet
);
406 else if( type
== k_classtype_particle_box
)
408 logic_particle_call( world
, ref
, packet
);
411 else if( type
== k_classtype_signal_splitter
)
413 logic_splitter( world
, ref
, packet
);
417 vg_error( "Undefined logic brick (entity type %d)\n", type
);
418 logic_packet_terminate( packet
);
425 VG_STATIC
void logic_bricks_world_gen_allocate( world_instance
*world
)
427 /* REVISION: unify allocations, loaders and extensions for entities.
428 * we currently seem to do every which entity a different way */
430 world
->logic_brick_count
= 0;
431 world
->logic_bricks
= NULL
;
432 world
->soundscape_count
= 0;
433 world
->trigger_count
= 0;
435 for( int i
=0; i
<world
->meta
->info
.node_count
; i
++ )
437 mdl_node
*pnode
= mdl_node_from_id( world
->meta
, i
);
439 if( pnode
->classtype
== k_classtype_logic_wire
||
440 pnode
->classtype
== k_classtype_logic_chances
||
441 pnode
->classtype
== k_classtype_soundscape
||
442 pnode
->classtype
== k_classtype_trigger
||
443 pnode
->classtype
== k_classtype_particle_box
||
444 pnode
->classtype
== k_classtype_signal_splitter
)
446 world
->logic_bricks
=
447 vg_linear_extend( world_global
.generic_heap
,
449 sizeof( struct logic_brick_ref
) );
451 pnode
->sub_uid
= world
->logic_brick_count
;
453 struct logic_brick_ref
*ref
=
454 &world
->logic_bricks
[ world
->logic_brick_count
];
456 ref
->internal_id
= 0;
458 if( pnode
->classtype
== k_classtype_soundscape
)
460 u32 id
= world
->soundscape_count
;
462 struct soundscape
*soundscape
= &world
->soundscapes
[ id
];
464 struct classtype_soundscape
*inf
=
465 mdl_get_entdata( world
->meta
, pnode
);
467 soundscape
->label
= mdl_pstr( world
->meta
, inf
->label
);
468 soundscape
->max_instances
= inf
->max_instances
;
469 soundscape
->allow_transitions
= inf
->allow_transitions
;
470 soundscape
->transition_duration
= inf
->transition_duration
;
471 v3_copy( pnode
->co
, soundscape
->spawn_position
);
473 ref
->internal_id
= id
;
474 world
->soundscape_count
++;
476 else if( pnode
->classtype
== k_classtype_trigger
||
477 pnode
->classtype
== k_classtype_particle_box
)
479 u32 id
= world
->trigger_count
;
480 struct trigger_zone
*trigger
= &world
->triggers
[ id
];
482 mdl_node_transform( pnode
, trigger
->transform
);
483 m4x3_invert_full( trigger
->transform
, trigger
->inv_transform
);
484 trigger
->target_logic_brick
= world
->logic_brick_count
;
485 trigger
->classtype
= pnode
->classtype
;
487 world
->trigger_count
++;
490 world
->logic_brick_count
++;
495 #endif /* WORLD_LOGIC_BRICKS_H */