refactor model things
[carveJwlIkooP6JGAAIwe30JlM.git] / world.h
diff --git a/world.h b/world.h
index 8b1b1dc079ff159e06e6197837f0637e4a6a1e46..8b650a5e0c169d336cd0b2a872fe640408c7d29d 100644 (file)
--- a/world.h
+++ b/world.h
@@ -94,8 +94,6 @@ VG_STATIC struct gworld
       u32  indices_head;
       u32  vertex_head;
 
-      float last_notch;
-
       struct route_ui_segment
       {
          float length;
@@ -112,6 +110,13 @@ VG_STATIC struct gworld
 
    v3f render_gate_pos;
    int active_route_board;
+   int in_trigger;
+
+   /* This is a small flag we use to changelevel.
+    * It will not be cleared until all sounds stop playing 
+    */
+   int   switching_to_new_world;
+   char  world_name[ 64 ];
 
    /*
     * Dynamically allocated when world_load is called.
@@ -122,7 +127,8 @@ VG_STATIC struct gworld
     * (world_gen.h)
     * --------------------------------------------------------------------------
     */
-   void *dynamic_vgl;
+   void *dynamic_vgl, 
+        *audio_vgl;  /* sub buffer of the audio buffer */
 
    /*
     * Main world .mdl 
@@ -157,42 +163,46 @@ VG_STATIC struct gworld
    u32 audio_things_count;
 
    /*
-    * Relays, random, etc
+    * Relays
     */
-   struct logic_entity
+   struct logic_relay
    {
       v3f pos;
-      enum logic_type logic_type;
-      int enabled;
 
-      /* indexes the action array */
-      u32 action_start, action_count;
+      struct relay_target
+      {
+         u32 sub_id;
+         enum classtype classtype;
+      }
+      targets[4];
+      u32 target_count;
    }
-   * logic_entities;
-   u32 logic_entity_count;
+   * logic_relays;
+   u32 relay_count;
 
    /*
-    * Action array
+    * Box trigger entities
     */
-   struct logic_action
+   struct trigger_zone
    {
-      u32 event,     /* on trigger, on enable, etc (TODO: Enum) */
-          target_id; /* thing to target, 0: self */
+      m4x3f transform, inv_transform;
 
+      struct relay_target target;
    }
-   * logic_actions;
-   u32 logic_action_count;
+   * triggers;
+   u32 trigger_count;
 
    /*
-    * Box trigger entities
+    * Achievements
     */
-   struct trigger_zone
+   struct logic_achievement
    {
-      m4x3f transform, inv_transform;
-      u32   trigger_entity;
+      v3f pos;
+      const char *achievement_id;
+      u32 achieved;
    }
-   * triggers;
-   u32 trigger_count;
+   * logic_achievements;
+   u32 achievement_count;
 
 
    /*
@@ -286,23 +296,12 @@ VG_STATIC struct gworld
 
    rigidbody rb_geo;
 
-   /* TODO Maybe make this less hardcoded */
+   /* TODO Maybe make this less hardcoded...
+    *      im on it, boss*/
    mdl_submesh sm_geo_std_oob,   sm_geo_std, sm_geo_vb,
                sm_foliage_main,  sm_foliage_alphatest,
                sm_graffiti, sm_subworld, sm_terrain;
 
-   /*
-    * Allocated AFTER all previous buffers are done
-    * --------------------------------------------------------------------------
-    */
-
-   struct instance_cache
-   {
-      mdl_context *mdl;
-      u32 pstr_file;
-   }
-   instance_cache[32];
-   u32 instance_cache_count;
 }
 world;
 
@@ -333,6 +332,47 @@ VG_STATIC int ray_world( v3f pos, v3f dir, ray_hit *hit );
  * -----------------------------------------------------------------------------
  */
 
+VG_STATIC int world_stop_sound( int argc, const char *argv[] )
+{
+   /* 
+    * None of our world audio runs as one shots, they always have a player.
+    * Therefore it is safe to delete clip data after the players are
+    * disconnected
+    */
+   audio_lock();
+   for( int i=0; i<world.audio_things_count; i++ )
+   {
+      struct world_audio_thing *at = &world.audio_things[i];
+
+      if( audio_player_is_playing( &at->player ) )
+      {
+         u32 cflags = audio_player_get_flags( &at->player );
+         audio_player_set_flags( &at->player, cflags | AUDIO_FLAG_KILL );
+      }
+   }
+   audio_unlock();
+
+   return 0;
+}
+
+VG_STATIC int world_change_world( int argc, const char *argv[] )
+{
+   if( argc == 0 )
+   {
+      vg_info( "%s\n", world.world_name );
+      return 0;
+   }
+   else
+   {
+      vg_info( "Switching world...\n" );
+      strcpy( world.world_name, argv[0] );
+      world.switching_to_new_world = 1;
+      world_stop_sound( 0, NULL );
+   }
+
+   return 0;
+}
+
 VG_STATIC void world_init(void)
 {
    vg_convar_push( (struct vg_convar){
@@ -343,6 +383,18 @@ VG_STATIC void world_init(void)
       .persistent = 0
    });
 
+       vg_function_push( (struct vg_cmd)
+   {
+               .name = "world_stop_sound",
+               .function = world_stop_sound
+       });
+
+       vg_function_push( (struct vg_cmd)
+   {
+               .name = "world",
+               .function = world_change_world
+       });
+
    world.sky_rate = 1.0;
    world.sky_target_rate = 1.0;
 
@@ -381,11 +433,109 @@ VG_STATIC void world_init(void)
 
    /* Allocate dynamic world memory arena */
    u32 max_size = 72*1024*1024;
-   world.dynamic_vgl = vg_create_linear_allocator( vg_mem.rtmemory, max_size );
+   world.dynamic_vgl = vg_create_linear_allocator( vg_mem.rtmemory, max_size,
+                                                   VG_MEMORY_SYSTEM );
+}
+
+VG_STATIC void world_audio_init(void)
+{
+   u32 size = vg_linear_remaining( vg_audio.audio_pool ) 
+               - sizeof(vg_linear_allocator);
+
+   world.audio_vgl = vg_create_linear_allocator( vg_audio.audio_pool, 
+                                                 size, VG_MEMORY_SYSTEM );
+}
+
+VG_STATIC void world_trigger_achievement( u32 uid )
+{
+   struct logic_achievement *ach = &world.logic_achievements[ uid ];
+
+   if( ach->achieved )
+      return;
+
+   steam_set_achievement( ach->achievement_id );
+   steam_store_achievements();
+
+   ach->achieved = 1;
+}
+
+VG_STATIC void world_run_relay( struct relay_target *rt );
+VG_STATIC void world_trigger_relay( u32 uid )
+{
+   struct logic_relay *relay = &world.logic_relays[ uid ];
+
+   for( int i=0; i<relay->target_count; i++ )
+   {
+      world_run_relay( &relay->targets[i] );
+   }
+}
+
+VG_STATIC void world_trigger_audio( u32 uid )
+{
+   struct world_audio_thing *wat = &world.audio_things[ uid ];
+
+   audio_lock();
+   audio_player_playclip( &wat->player, 
+                          &wat->temp_embedded_clip );
+   audio_unlock();
+}
+
+VG_STATIC void world_run_relay( struct relay_target *rt )
+{
+   struct entity_instruction
+   {
+      enum classtype classtype;
+      void (*p_trigger)( u32 uid );
+   }
+   entity_instructions[] =
+   {
+      { k_classtype_logic_achievement, world_trigger_achievement },
+      { k_classtype_logic_relay, world_trigger_relay },
+      { k_classtype_audio, world_trigger_audio }
+   };
+
+   for( int i=0; i<vg_list_size(entity_instructions); i++ )
+   {
+      struct entity_instruction *instr = &entity_instructions[i];
+
+      if( instr->classtype == rt->classtype )
+      {
+         instr->p_trigger( rt->sub_id );
+         return;
+      }
+   }
+
+   vg_error( "Don't know how to trigger classtype %d\n", rt->classtype );
 }
 
 VG_STATIC void world_update( v3f pos )
 {
+   if( world.switching_to_new_world )
+   {
+      int all_stopped = 1;
+
+      audio_lock();
+      for( int i=0; i<world.audio_things_count; i++ )
+      {
+         struct world_audio_thing *at = &world.audio_things[i];
+
+         if( audio_player_is_playing( &at->player ) )
+         {
+            all_stopped = 0;
+            break;
+         }
+      }
+      audio_unlock();
+
+      if( all_stopped )
+      {
+         world.switching_to_new_world = 0;
+         world_unload();
+         world_load();
+      }
+   }
+
+
    world.sky_time += world.sky_rate * vg.time_delta;
    world.sky_rate = vg_lerp( world.sky_rate, world.sky_target_rate, 
                                  vg.time_delta * 5.0 );
@@ -429,14 +579,10 @@ VG_STATIC void world_update( v3f pos )
       }
    }
 
-#if 0
-   VG_STATIC int in_zone = 0;
-
-   int in_zone_this_time = 0;
-
-   for( int i=0; i<world.achievement_zones_count; i++ )
+   int in_trigger = 0;
+   for( int i=0; i<world.trigger_count; i++ )
    {
-      struct achievement_zone *zone = &world.achievement_zones[i];
+      struct trigger_zone *zone = &world.triggers[i];
 
       v3f local;
       m4x3_mulv( zone->inv_transform, pos, local );
@@ -445,23 +591,12 @@ VG_STATIC void world_update( v3f pos )
           (fabsf(local[1]) <= 1.0f) &&
           (fabsf(local[2]) <= 1.0f) )
       {
-         in_zone_this_time = 1;
+         in_trigger = 1;
 
-         if( !in_zone && zone->ptarget )
+         if( !world.in_trigger )
          {
-            audio_lock();
-            audio_player_playclip( &zone->ptarget->player, 
-                                   &zone->ptarget->temp_embedded_clip );
-            audio_unlock();
+            world_run_relay( &zone->target );
          }
-
-         if( !zone->triggered )
-         {
-            steam_set_achievement( zone->name );
-            steam_store_achievements();
-         }
-
-         zone->triggered = 1;
       }
 
       vg_line_boxf_transformed( zone->transform, (boxf){{-1.0f,-1.0f,-1.0f},
@@ -469,9 +604,7 @@ VG_STATIC void world_update( v3f pos )
                                                         0xff00ff00 );
    }
 
-   in_zone = in_zone_this_time;
-#endif
-   
+   world.in_trigger = in_trigger;
    sfd_update();
 }