--- /dev/null
+#include "ent_region.h"
+#include "gui.h"
+
+static void ent_region_call( world_instance *world, ent_call *call ){
+ ent_region *region =
+ mdl_arritm( &world->ent_region, mdl_entity_id_id(call->id) );
+
+ if( !region->zone_volume )
+ return;
+
+ ent_volume *volume =
+ mdl_arritm( &world->ent_volume, mdl_entity_id_id(region->zone_volume) );
+
+ if( call->function == 0 ){ /* enter */
+ for( u32 i=0; i<mdl_arrcount(&world->ent_route); i ++ ){
+ ent_route *route = mdl_arritm( &world->ent_route, i );
+
+ v3f local;
+ m4x3_mulv( volume->to_local, route->board_transform[3], local );
+ if( (fabsf(local[0]) <= 1.0f) &&
+ (fabsf(local[1]) <= 1.0f) &&
+ (fabsf(local[2]) <= 1.0f) ){
+ route->flags &= ~k_ent_route_flag_out_of_zone;
+ }
+ else {
+ route->flags |= k_ent_route_flag_out_of_zone;
+ }
+ }
+
+ gui_location_print_ccmd( 1, (const char *[]){
+ mdl_pstr(&world->meta,region->pstr_title)} );
+ }
+ else if( call->function == 1 ){ /* leave */
+ for( u32 i=0; i<mdl_arrcount(&world->ent_route); i ++ ){
+ ent_route *route = mdl_arritm( &world->ent_route, i );
+ route->flags |= k_ent_route_flag_out_of_zone;
+ }
+ }
+}
+
+/*
+ * reevaluate all achievements to calculate the compiled achievement
+ */
+static void ent_region_re_eval( world_instance *world ){
+ for( u32 i=0; i<mdl_arrcount(&world->ent_region); i ++ ){
+ ent_region *region = mdl_arritm(&world->ent_region, i);
+
+ if( !region->zone_volume )
+ continue;
+
+ ent_volume *volume = mdl_arritm(&world->ent_volume,
+ mdl_entity_id_id(region->zone_volume));
+
+ u32 combined = k_ent_route_flag_achieve_gold |
+ k_ent_route_flag_achieve_silver;
+
+ for( u32 j=0; j<mdl_arrcount(&world->ent_route); j ++ ){
+ ent_route *route = mdl_arritm(&world->ent_route, j );
+
+ v3f local;
+ m4x3_mulv( volume->to_local, route->board_transform[3], local );
+ if( !((fabsf(local[0]) <= 1.0f) &&
+ (fabsf(local[1]) <= 1.0f) &&
+ (fabsf(local[2]) <= 1.0f)) ){
+ continue;
+ }
+
+ combined &= route->flags;
+ }
+
+ region->flags = combined;
+
+ /* TODO: Challenges */
+ }
+}