exploding boxes and interacter volumes
authorhgn <hgodden00@gmail.com>
Wed, 12 Mar 2025 19:58:16 +0000 (19:58 +0000)
committerhgn <hgodden00@gmail.com>
Wed, 12 Mar 2025 19:58:16 +0000 (19:58 +0000)
26 files changed:
content_skaterift/maps/dev_hub/main.mdl
content_skaterift/maps/dev_tutorial/main.mdl
content_skaterift/maps/mp_mtzero/main.mdl
content_skaterift/maps/sr002-local-dev_tutorial-cm-docks-fast.qoi [new file with mode: 0644]
content_skaterift/maps/sr002-local-dev_tutorial-cm-hub-tutorial.qoi
content_skaterift/maps/sr002-local-mp_mtzero-cm-docks-fast.qoi [new file with mode: 0644]
content_skaterift/maps/sr002-local-mp_mtzero-cm-straw.qoi
content_skaterift/metascenes/unlock_city.ms [new file with mode: 0644]
content_skaterift/metascenes/unlock_mtzero.ms [new file with mode: 0644]
content_skaterift/metascenes/unlock_valley.ms [new file with mode: 0644]
content_skaterift/sound/woodbreak.ogg [new file with mode: 0644]
skaterift_blender/sr_main.py
skaterift_blender/sr_mdl.py
src/audio.c
src/entity.h
src/menu.c
src/metascene.c
src/particle.c
src/scripts/blocker_break.c [new file with mode: 0644]
src/scripts/hub.c
src/scripts/tutorial_island.c
src/skaterift_script.c
src/world.h
src/world_entity.c
src/world_volumes.c
src/world_volumes.h

index 4ce03aeab17072a534b69146bff86dec44f2667d..2baa0f7143ccfcb54affe300ffd46c66c4ac4622 100644 (file)
Binary files a/content_skaterift/maps/dev_hub/main.mdl and b/content_skaterift/maps/dev_hub/main.mdl differ
index f4de6ed6accafce6f9db0078a784ac2da6a894a2..38bef2a30b34f0993261817b7013b1d62d177c1d 100644 (file)
Binary files a/content_skaterift/maps/dev_tutorial/main.mdl and b/content_skaterift/maps/dev_tutorial/main.mdl differ
index ed318b459fce67e81686c5b2c799a05dce70ef47..b6b8ed8a1451e515b694d2c257db752764c5a0a9 100644 (file)
Binary files a/content_skaterift/maps/mp_mtzero/main.mdl and b/content_skaterift/maps/mp_mtzero/main.mdl differ
diff --git a/content_skaterift/maps/sr002-local-dev_tutorial-cm-docks-fast.qoi b/content_skaterift/maps/sr002-local-dev_tutorial-cm-docks-fast.qoi
new file mode 100644 (file)
index 0000000..701efb1
Binary files /dev/null and b/content_skaterift/maps/sr002-local-dev_tutorial-cm-docks-fast.qoi differ
index 4dc48f1f39689c06e32f5f20cc9ade3602bbcae0..35492c5c54e14edaeb5703387240660e1900e1d0 100644 (file)
Binary files a/content_skaterift/maps/sr002-local-dev_tutorial-cm-hub-tutorial.qoi and b/content_skaterift/maps/sr002-local-dev_tutorial-cm-hub-tutorial.qoi differ
diff --git a/content_skaterift/maps/sr002-local-mp_mtzero-cm-docks-fast.qoi b/content_skaterift/maps/sr002-local-mp_mtzero-cm-docks-fast.qoi
new file mode 100644 (file)
index 0000000..11e7199
Binary files /dev/null and b/content_skaterift/maps/sr002-local-mp_mtzero-cm-docks-fast.qoi differ
index 7bca803e9b149c231b9531f230906c5f73bebe08..141e75de50643147a74955cfc465e82e5ded9792 100644 (file)
Binary files a/content_skaterift/maps/sr002-local-mp_mtzero-cm-straw.qoi and b/content_skaterift/maps/sr002-local-mp_mtzero-cm-straw.qoi differ
diff --git a/content_skaterift/metascenes/unlock_city.ms b/content_skaterift/metascenes/unlock_city.ms
new file mode 100644 (file)
index 0000000..001e689
Binary files /dev/null and b/content_skaterift/metascenes/unlock_city.ms differ
diff --git a/content_skaterift/metascenes/unlock_mtzero.ms b/content_skaterift/metascenes/unlock_mtzero.ms
new file mode 100644 (file)
index 0000000..c61668e
Binary files /dev/null and b/content_skaterift/metascenes/unlock_mtzero.ms differ
diff --git a/content_skaterift/metascenes/unlock_valley.ms b/content_skaterift/metascenes/unlock_valley.ms
new file mode 100644 (file)
index 0000000..77285f1
Binary files /dev/null and b/content_skaterift/metascenes/unlock_valley.ms differ
diff --git a/content_skaterift/sound/woodbreak.ogg b/content_skaterift/sound/woodbreak.ogg
new file mode 100644 (file)
index 0000000..2d06401
Binary files /dev/null and b/content_skaterift/sound/woodbreak.ogg differ
index fb3a5a259b8045ba862ae05c05e598fd46f253d8..ab637bdef0d0a2e26d8ddfee31f17e70ff0d1c6b 100644 (file)
@@ -329,10 +329,17 @@ class volume_particles(Structure):
                ("blank2",c_uint32)]
 #}
 
+class volume_interact(Structure):
+#{
+   _fields_ = [("event",c_uint32),
+               ("pstr_text",c_int32)]
+#}
+
 class volume_union(Union):
 #{
    _fields_ = [("trigger",volume_trigger),
-               ("particles",volume_particles)]
+               ("particles",volume_particles),
+               ("interact",volume_interact)]
 #}
 
 class ent_volume(Structure):
@@ -1653,7 +1660,8 @@ class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):#{
    subtype: bpy.props.EnumProperty(
       name="Subtype",
       items=[('0','Trigger',''),
-             ('1','Particles (0.1s)','')]
+             ('1','Particles (0.1s)',''),
+             ('2','Interact','')]
    )
 
    target: bpy.props.PointerProperty( \
@@ -1663,6 +1671,7 @@ class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):#{
    target_event_leave: bpy.props.IntProperty( name="Leave Ev", default=-1 )
 
    auto_run: bpy.props.BoolProperty( name="Auto Run" )
+   text: bpy.props.StringProperty()
 
    @staticmethod
    def inspect_target( layout, data, propname, evs = ['_event'], text='' ):#{
@@ -1695,10 +1704,12 @@ class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):#{
    #}
 
    @staticmethod
-   def sr_inspector( layout, data ):#{
+   def sr_inspector( layout, data ):
+   #{
       layout.prop( data[0], 'subtype' )
       SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target', ['_event','_event_leave'] )
-      layout.prop( data[0], 'auto_run' )
+      if data[0].subtype == '2':
+         layout.prop( data[0], 'text' )
    #}
 #}
 
@@ -2788,19 +2799,20 @@ def cv_ent_volume( obj ):
 
    data = obj.SR_data.ent_volume[0]
 
-   if data.subtype == '0':#{
-      cv_draw_ucube( obj.matrix_world, (0,1,0), Vector((0.99,0.99,0.99)) )
+   if data.subtype == '0':
+      cc = (0,1,0)
+   elif data.subtype == '1':
+      cc = (1,1,0)
+   elif data.subtype == '2':
+      cc = (1,0,0)
+   else:
+      cc = (0,0,0)
 
-      if data.target:#{
-         cv_draw_arrow( obj.location, data.target.location, (1,1,1) )
-      #}
-   #}
-   elif data.subtype == '1':#{
-      cv_draw_ucube( obj.matrix_world, (1,1,0) )
+   cv_draw_ucube( obj.matrix_world, cc, Vector((0.99,0.99,0.99)) )
 
-      if data.target:#{
-         cv_draw_arrow( obj.location, data.target.location, (1,1,1) )
-      #}
+   if data.target:
+   #{
+      cv_draw_arrow( obj.location, data.target.location, (1,1,1) )
    #}
 #}
 
index 4af7a41d37e8a657e7eb1a723d33d6e80044d8f2..f84e5fa794c66f5734eca1c8005a0805d1fe1eec 100644 (file)
@@ -741,16 +741,32 @@ def _mdl_compiler_compile_entities():
             #}
             sr_ent_push( audio )
          #}
-         elif ent_type == 'ent_volume':#{
+         elif ent_type == 'ent_volume':
+         #{
             obj_data = obj.SR_data.ent_volume[0]
             volume = ent_volume()
-            volume.flags = int(obj_data.subtype)
-            if obj_data.auto_run:
-               volume.flags |= 0x4
+            volume.flags = 0x00
+
+            if obj_data.subtype == '1':
+               volume.flags |= 0x1
+
+            #if obj_data.auto_run:
+            #   volume.flags |= 0x4
             compile_obj_transform( obj, volume.transform )
 
-            if obj_data.target:#{
+            if obj_data.target:
+            #{
                volume.target = sr_entity_id( obj_data.target )
+            #}
+
+            if obj_data.subtype == '2':
+            #{
+               volume.flags |= 0x8
+               volume._anon.interact.event = obj_data.target_event
+               volume._anon.interact.pstr_text = _af_pack_string( obj_data.text )
+            #}
+            else:
+            #{
                volume._anon.trigger.event = obj_data.target_event
                volume._anon.trigger.event_leave = obj_data.target_event_leave
             #}
index d5eaed1ceb7f955bd7119a8ffec45fdf49225410..463269b1e8e62b7ee7c6ccde072f313cf99c8ce6 100644 (file)
@@ -116,6 +116,11 @@ audio_clip audio_gate_ambient = {
 .path = "sound/gate_ambient.ogg"
 };
 
+audio_clip audio_wood_break = 
+{
+.path = "sound/woodbreak.ogg"
+};
+
 audio_clip audio_rewind[] = {
 { .path = "sound/rewind_start.ogg" },
 { .path = "sound/rewind_end_1.5.ogg" },
@@ -192,6 +197,7 @@ void audio_init(void)
    audio_clip_loadn( &audio_gate_pass, 1, NULL );
    audio_clip_loadn( &audio_gate_lap, 1, NULL );
    audio_clip_loadn( &audio_gate_ambient, 1, NULL );
+   audio_clip_loadn( &audio_wood_break, 1, NULL );
 
    audio_clip_loadn( audio_jumps, VG_ARRAY_LEN(audio_jumps), NULL );
    audio_clip_loadn( audio_lands, VG_ARRAY_LEN(audio_lands), NULL );
index 84bb832b91efee26ba83d8218bee80c255168a3d..50a1ae7c76c2aab72e915a7ec1a26c9537f40a06 100644 (file)
@@ -15,6 +15,7 @@ typedef struct ent_water ent_water;
 typedef struct ent_audio_clip ent_audio_clip;
 typedef struct volume_particles volume_particles;
 typedef struct volume_trigger volume_trigger;
+typedef struct volume_interact volume_interact;
 typedef struct ent_volume ent_volume;
 typedef struct ent_audio ent_audio;
 typedef struct ent_marker ent_marker;
@@ -322,20 +323,29 @@ struct volume_trigger{
    i32 event, event_leave;
 };
 
+struct volume_interact
+{
+   i32 activate_event;
+   u32 pstr_text;
+};
+
 enum ent_volume_flag {
    k_ent_volume_flag_particles = 0x1,
    k_ent_volume_flag_disabled  = 0x2,
-   k_ent_volume_flag_autorun   = 0x4
+   k_ent_volume_flag_interact  = 0x8
 };
 
-struct ent_volume{
+struct ent_volume
+{
    mdl_transform transform;
    m4x3f to_world, to_local;
    u32 flags;
 
    u32 target;
-   union{
+   union
+   {
       volume_trigger trigger;
+      volume_interact interact;
       volume_particles particles;
    };
 };
@@ -647,7 +657,6 @@ struct ent_challenge
    u32 camera_id;
 
    u32 status;
-   u32 visible_when_unlocked_id;
 };
 
 struct ent_relay {
index ffba128efb9f6cbe058ee6f7edbd437c0b81e00e..13ecff13460fe7bfe96de5ad6880a5941c8fc365 100644 (file)
@@ -379,7 +379,7 @@ void menu_update_world_list(void)
    if( world_map.superworld_list_selected == k_superworld_infinite ) world_map.selected_superworld_locked = 1;
    if( world_map.superworld_list_selected == k_superworld_venus_moon )
    {
-      world_map.selected_superworld_locked = !_skaterift_script_nugget_status( "ch4s3" );
+      world_map.selected_superworld_locked = !_skaterift_script_nugget_status( "unlock_venus" );
    }
 
    if( world_map.selected_superworld_locked )
@@ -418,11 +418,11 @@ void menu_update_world_list(void)
          bool unlocked = 1;
 
          if( reg->flags & ADDON_REG_MTZERO )
-            unlocked = _skaterift_script_nugget_status( "ch2s1" )?1:0;
+            unlocked = _skaterift_script_nugget_status( "unlock_mtzero" )?1:0;
          if( reg->flags & ADDON_REG_CITY )
-            unlocked = _skaterift_script_nugget_status( "ch3s1" )?1:0;
+            unlocked = _skaterift_script_nugget_status( "unlock_city" )?1:0;
          if( reg->flags & ADDON_REG_VALLEY )
-            unlocked = _skaterift_script_nugget_status( "ch4s1a" )?1:0;
+            unlocked = _skaterift_script_nugget_status( "unlock_valley" )?1:0;
 
          menu.world_list_entries[ menu.world_list_display_count ] = unlocked? reg: NULL;
 
index 19b7dbdc79d1ddc99d653a3d3550059ded0f7913..c18b4dfa278a0d11a0e119092601e8c71eb7542d 100644 (file)
@@ -824,7 +824,6 @@ void cutscene_render_fadeout(void)
    {
       glEnable(GL_BLEND);
       glDisable(GL_DEPTH_TEST);
-      glDepthMask(GL_FALSE);
       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
       glBlendEquation(GL_FUNC_ADD);
 
index ec2960b7784bd588e598163c5afa68a61cfee6e6..58bc3ed874df7aa91f7d4dc025650ddebb1e8522 100644 (file)
@@ -14,10 +14,10 @@ particles_env = {
    .width = 0.25f
 };
 
-void particle_spawn( particle_system *sys, v3f co, v3f v,
-                     f32 lifetime, u32 colour )
+void particle_spawn( particle_system *sys, v3f co, v3f v, f32 lifetime, u32 colour )
 {
-   if( sys->alive == sys->max ) return;
+   if( sys->alive == sys->max ) 
+      return;
 
    particle *p = &sys->array[ sys->alive ++ ];
    v3_copy( co, p->co );
@@ -30,7 +30,8 @@ void particle_spawn_cone( particle_system *sys,
                           v3f co, v3f dir, f32 angle, f32 speed, 
                           f32 lifetime, u32 colour )
 {
-   if( sys->alive == sys->max ) return;
+   if( sys->alive == sys->max ) 
+      return;
 
    particle *p = &sys->array[ sys->alive ++ ];
 
diff --git a/src/scripts/blocker_break.c b/src/scripts/blocker_break.c
new file mode 100644 (file)
index 0000000..37f9a11
--- /dev/null
@@ -0,0 +1,64 @@
+void _explode_template_boom( ent_script_event *event )
+{
+   ent_list_set_visible( event->world, event->entity_list, 0 );
+
+   v3f where = {0,0,0};
+
+   ent_list *list = event->entity_list;
+   for( u32 i=0; i<list->entity_ref_count; i ++ )
+   {
+      file_entity_ref *ref = af_arritm( &event->world->file_entity_ref, list->entity_ref_start + i );
+      
+      u32 type = mdl_entity_id_type( ref->entity_id ),
+          index = mdl_entity_id_id( ref->entity_id );
+
+      if( type == k_ent_marker )
+      {
+         ent_marker *marker = af_arritm( &event->world->ent_marker, index );
+         for( u32 j=0; j<80; j ++ )
+         {
+            particle_spawn_cone( &particles_env, marker->transform.co, 
+                                 (v3f){0,1,0}, 1.2f, vg_randf64(&vg.rand) * 8.5f, 5.0f, 0xff76b6ea );
+         }
+         v3_copy( marker->transform.co, where );
+      }
+   }
+   vg_audio_lock();
+   vg_audio_oneshot_3d( &audio_wood_break, where, 100.0f, 1.0f, 0, 0 );
+   vg_audio_unlock();
+}
+
+static bool _skaterift_script_blocker_break_template( ent_script_event *event, 
+                                                      const struct generic_cutscene *cutscene_template,
+                                                      const char *once_nugget_trigger  )
+{
+   static const struct generic_cutscene cutscene = 
+   {
+      .metascene_path = "metascenes/unlock_docks.ms",
+      .freeze_player = 1,
+   };
+   generic_cutscene_wrapper( &cutscene, event );
+
+   if( on_function_trigger( event, 1 ) )
+   {
+      vg_error( "Show required objectives here\n" );
+   }
+
+   if( on_function_trigger( event, 2 ) )
+   {
+      if( on_nugget_once( event, "unlock_docks_view" ) )
+      {
+         play_generic_cutscene( event );
+      }
+      else
+      {
+         ent_list_set_visible( event->world, event->entity_list, 0 );
+      }
+   }
+
+   if( on_cutscene_marker( event, "$break" ) )
+   {
+   }
+
+   return 1;
+}
index 3ff89651691046991291d671ebb90653e6491882..6d28fecfcf899e9a052f1ff4d07e535e901263d6 100644 (file)
@@ -35,6 +35,7 @@ static bool _skaterift_script_hub( ent_script_event *event )
             if( skaterift.achievements & 0x8 )
                prop->flags &= ~0x1;
 
+#if 0
          if( AF_STR_EQ( &world->meta.af, prop->pstr_alias, "main_island_block" ) )
             if( unlock_mtzero )
                prop->flags |= k_prop_flag_hidden;
@@ -50,6 +51,7 @@ static bool _skaterift_script_hub( ent_script_event *event )
          if( AF_STR_EQ( &world->meta.af, prop->pstr_alias, "valley_block" ) )
             if( unlock_valley )
                prop->flags |= k_prop_flag_hidden;
+#endif
       }
 
       u32 spawns_allowed = 0;
@@ -76,3 +78,63 @@ static bool _skaterift_script_hub( ent_script_event *event )
    return 0;
 }
 
+static void _hub_blocker_template( ent_script_event *event, const char *unlock, const char *guard )
+{
+   u64 status;
+   if( on_nugget_changed( event, unlock, &status ) )
+   {
+      if( status )
+      {
+         if( on_nugget_once( event, guard ) )
+         {
+            play_generic_cutscene( event );
+         }
+         else
+         {
+            ent_list_set_visible( event->world, event->entity_list, 0 );
+         }
+      }
+   }
+
+   if( on_cutscene_marker( event, "$break" ) )
+   {
+      _explode_template_boom( event );
+   }
+
+}
+
+static bool _skaterift_script_unlock_mtzero( ent_script_event *event )
+{
+   static const struct generic_cutscene cutscene = 
+   {
+      .metascene_path = "metascenes/unlock_mtzero.ms",
+      .freeze_player = 1,
+   };
+   generic_cutscene_wrapper( &cutscene, event );
+   _hub_blocker_template( event, "unlock_mtzero", "unlock_mtzero_view" );
+   return 1;
+}
+
+static bool _skaterift_script_unlock_city( ent_script_event *event )
+{
+   static const struct generic_cutscene cutscene = 
+   {
+      .metascene_path = "metascenes/unlock_city.ms",
+      .freeze_player = 1,
+   };
+   generic_cutscene_wrapper( &cutscene, event );
+   _hub_blocker_template( event, "unlock_city", "unlock_city_view" );
+   return 1;
+}
+
+static bool _skaterift_script_unlock_valley( ent_script_event *event )
+{
+   static const struct generic_cutscene cutscene = 
+   {
+      .metascene_path = "metascenes/unlock_valley.ms",
+      .freeze_player = 1,
+   };
+   generic_cutscene_wrapper( &cutscene, event );
+   _hub_blocker_template( event, "unlock_valley", "unlock_valley_view" );
+   return 1;
+}
index 788000cc0c336603bdd01aa7076900150dd8a4b6..b433411b63048b4949f3388b4153db6954f84fdc 100644 (file)
@@ -51,7 +51,7 @@ static bool _skaterift_script_unlock_docks( ent_script_event *event )
 
    if( on_cutscene_marker( event, "$break" ) )
    {
-      ent_list_set_visible( event->world, event->entity_list, 0 );
+      _explode_template_boom( event );
    }
 
    return 1;
@@ -191,10 +191,23 @@ static bool _skaterift_script_ch1s6a( ent_script_event *event )
       _skaterift_script_nugget_set( "unlock_mtzero", 1 );
    }
 
-   if( cs_event == k_generic_cutscene_event_end )
+   return 1;
+}
+
+static bool _skaterift_script_final_portal( ent_script_event *event )
+{
+   u64 status;
+   if( on_nugget_changed( event, "unlock_mtzero", &status ) )
    {
-      /* move level to the hub */
-   }
+      world_instance *world = event->world;
+      file_entity_ref *ref = af_arritm( &world->file_entity_ref, event->entity_list->entity_ref_start );
+
+      u32 type = mdl_entity_id_type( ref->entity_id ),
+          index = mdl_entity_id_id( ref->entity_id );
 
+      ent_gate *gate = af_arritm( &event->world->ent_gate, index );
+      if( status ) gate->flags &= ~((u32)k_ent_gate_locked);
+      else         gate->flags |=   (u32)k_ent_gate_locked;
+   }
    return 1;
 }
index e44a2326d7ed07cd55de886a3368570caad57f0f..939c023bc8ca05307cb5f2c199735f1744e28d9d 100644 (file)
@@ -1568,6 +1568,7 @@ enum generic_cutscene_event challenge_video_wrapper( const struct generic_cutsce
    return cs_event;
 }
 
+#include "scripts/blocker_break.c"
 #include "scripts/heaven.c"
 #include "scripts/hub.c"
 #include "scripts/tutorial_island.c"
@@ -1588,6 +1589,12 @@ struct ent_script_table_entry _ent_script_table[] =
    { "ch1s5", _skaterift_script_ch1s5 },
    { "ch1s6a", _skaterift_script_ch1s6a },
    { "unlock_docks", _skaterift_script_unlock_docks },
+   { "final_portal", _skaterift_script_final_portal },
+
+   { "unlock_mtzero", _skaterift_script_unlock_mtzero },
+   { "unlock_city", _skaterift_script_unlock_city },
+   { "unlock_valley", _skaterift_script_unlock_valley },
+
 
    { NULL }
 };
@@ -1617,8 +1624,15 @@ _skaterift_script_savedata[] =
    { "unlock_docks_view" },
 
    { "unlock_mtzero" },
+   { "unlock_mtzero_view" },
+
    { "unlock_city" },
-   { "unlock_valley" }
+   { "unlock_city_view" },
+
+   { "unlock_valley" },
+   { "unlock_valley_view" },
+
+   { "unlock_venus" },
 };
 
 u64 _skaterift_script_nugget_status( const char *nugget_alias )
index 5f39110cb25f32e74c8ef1f3ea5b86b319204f67..5342289c661f030c73ce5987d32ba178fac9d8bb 100644 (file)
@@ -261,7 +261,8 @@ struct world_static
       k_world_event_none = 0,
       k_world_event_challenge,
       k_world_event_shop,
-      k_world_event_route_leaderboard
+      k_world_event_route_leaderboard,
+      k_world_event_interact
    }
    event;
 
index dcedb84cc6ab8fe4bb7034229912bb86b44eb7ef..cca108d6780e1466aab42a5e4ec2cc3359a9fca5 100644 (file)
@@ -878,7 +878,6 @@ void world_entity_start( world_instance *world, vg_msg *sav )
    }
 
    ent_region_re_eval( world );
-   world_volumes_start( world );
    ent_script_start( world );
 }
 
index 1e6637857ad2e0c6e9490b4b7da28ef5fc358ef9..f92ebc1c4d0457e67eda805c3ca7fc691456411e 100644 (file)
@@ -1,21 +1,6 @@
 #include "world_volumes.h"
 
-void world_volumes_start( world_instance *world )
-{
-   for( u32 i=0; i<af_arrcount(&world->ent_volume); i ++ )
-   {
-      ent_volume *volume = af_arritm( &world->ent_volume, i );
-      
-      if( volume->flags & k_ent_volume_flag_autorun )
-      {
-         ent_call basecall;
-         basecall.id = mdl_entity_id( k_ent_volume, i );
-         basecall.data = NULL;
-         basecall.function = 0;
-         entity_call( world, &basecall );
-      }
-   }
-}
+struct _world_volumes _world_volumes;
 
 void world_volumes_update( world_instance *world, v3f pos )
 {
@@ -38,17 +23,30 @@ void world_volumes_update( world_instance *world, v3f pos )
       }
       else
       {
-         /* 
-          * LEGACY BEHAVIOUR: < v104 does not have leave events
-          */
-         if( world->meta.version >= 104 )
+         if( volume->flags & k_ent_volume_flag_interact )
          {
-            ent_call basecall;
-            basecall.function = k_ent_function_trigger_leave;
-            basecall.id = mdl_entity_id( k_ent_volume, idx );
-            basecall.data = NULL;
-
-            entity_call( world, &basecall );
+            if( _world.event == k_world_event_interact )
+            {
+               if( world_clear_event( k_world_event_interact ) )
+               {
+                  gui_helper_reset( k_gui_helper_mode_clear );
+               }
+            }
+         }
+         else
+         {
+            /* 
+             * LEGACY BEHAVIOUR: < v104 does not have leave events
+             */
+            if( world->meta.version >= 104 )
+            {
+               ent_call basecall;
+               basecall.function = k_ent_function_trigger_leave;
+               basecall.id = mdl_entity_id( k_ent_volume, idx );
+               basecall.data = NULL;
+
+               entity_call( world, &basecall );
+            }
          }
       }
    }
@@ -81,11 +79,15 @@ void world_volumes_update( world_instance *world, v3f pos )
          continue;
 
       ent_volume *volume = af_arritm( &world->ent_volume, index );
+      vg_line_cross( volume->to_world[3], 0xffffffff, 1.0f );
+      boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}};
 
       if( volume->flags & k_ent_volume_flag_disabled )
+      {
+         vg_line_boxf_transformed( volume->to_world, cube, 0xff000000 );
          continue;
+      }
 
-      boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}};
       if( volume->flags & k_ent_volume_flag_particles )
       {
          vg_line_boxf_transformed( volume->to_world, cube, 0xff00c0ff );
@@ -116,18 +118,54 @@ void world_volumes_update( world_instance *world, v3f pos )
              (fabsf(local[1]) <= 1.0f) &&
              (fabsf(local[2]) <= 1.0f) )
          {
-            ent_call basecall;
-            basecall.function = 0;
-            basecall.id = id;
-            basecall.data = NULL;
-
-            entity_call( world, &basecall );
-            _world.active_trigger_volumes[ 
-               _world.active_trigger_volume_count ++ ] = index;
+            if( volume->flags & k_ent_volume_flag_interact )
+            {
+               if( world_set_event( k_world_event_interact ) )
+               {
+                  gui_helper_reset( k_gui_helper_mode_black_bars );
+                  vg_str text;
+                  if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
+                     vg_strcat( &text, af_str( &world->meta.af, volume->interact.pstr_text ) );
+                  _world_volumes.active_volume_interact = volume;
+               }
+            }
+            else
+            {
+               ent_call basecall;
+               basecall.function = 0;
+               basecall.id = id;
+               basecall.data = NULL;
+               entity_call( world, &basecall );
+            }
+            _world.active_trigger_volumes[ _world.active_trigger_volume_count ++ ] = index;
          }
          else
             vg_line_boxf_transformed( volume->to_world, cube, 0xffcccccc );
       }
 next_volume:;
    }
+
+   if( _world.event == k_world_event_interact )
+   {
+      if( button_down( k_srbind_maccept ) )
+      {
+         ent_volume *volume = _world_volumes.active_volume_interact;
+         if( volume->target )
+         {
+            srinput.state = k_input_state_resume;
+
+            ent_call call;
+            call.data = NULL;
+            call.function = volume->interact.activate_event;
+            call.id = volume->target;
+            entity_call( &_world.main, &call );
+
+            if( world_clear_event( k_world_event_interact ) )
+            {
+               _world_volumes.active_volume_interact = NULL;
+               gui_helper_reset( k_gui_helper_mode_clear );
+            }
+         }
+      }
+   }
 }
index ba88a039b469ad0158ec98f9e140b4e8b4f24612..f9a7481ff659cf3423d9524de020488470cfb6ae 100644 (file)
@@ -2,5 +2,11 @@
 #include "world.h"
 #include "vg/vg_bvh.h"
 
+struct _world_volumes
+{
+   ent_volume *active_volume_interact;
+}
+extern _world_volumes;
+
 void world_volumes_update( world_instance *world, v3f pos );
 void world_volumes_start( world_instance *world );