yeaaaaaaaaaaa
authorhgn <hgodden00@gmail.com>
Wed, 21 May 2025 01:32:59 +0000 (02:32 +0100)
committerhgn <hgodden00@gmail.com>
Wed, 21 May 2025 01:32:59 +0000 (02:32 +0100)
122 files changed:
content_skaterift/maps/dev_tutorial/main.mdl
content_skaterift/maps/mp_line1/main.mdl
content_skaterift/maps/mp_spawn/main.mdl
content_skaterift/metascenes/battery_intro.ms [deleted file]
content_skaterift/metascenes/ch1s2.ms
content_skaterift/metascenes/ch1s3.ms [deleted file]
content_skaterift/metascenes/ch1s3b.ms [deleted file]
content_skaterift/metascenes/ch1s4.ms [deleted file]
content_skaterift/metascenes/ch1s5.ms
content_skaterift/metascenes/ch1s6a.ms [deleted file]
content_skaterift/metascenes/ch2e1.ms [deleted file]
content_skaterift/metascenes/ch2s1.ms [deleted file]
content_skaterift/metascenes/ch2s2.ms [deleted file]
content_skaterift/metascenes/ch2s3a.ms [deleted file]
content_skaterift/metascenes/ch2s4.ms [deleted file]
content_skaterift/metascenes/ch2s5.ms [deleted file]
content_skaterift/metascenes/ch2s6.ms [deleted file]
content_skaterift/metascenes/ch3s1.ms [deleted file]
content_skaterift/metascenes/ch3s2.ms [deleted file]
content_skaterift/metascenes/ch3s3.ms [deleted file]
content_skaterift/metascenes/ch4s1.ms [deleted file]
content_skaterift/metascenes/ch4s1a.ms [deleted file]
content_skaterift/metascenes/ch4s2.ms [deleted file]
content_skaterift/metascenes/ch4s3.ms [deleted file]
content_skaterift/metascenes/grave/battery_intro.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch1s2.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch1s3.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch1s3b.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch1s4.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch1s5.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch1s6a.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch2e1.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch2s1.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch2s2.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch2s3a.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch2s4.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch2s5.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch2s6.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch3s1.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch3s2.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch3s3.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch4rk.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch4s1.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch4s1a.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch4s2.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/ch4s3.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/intro.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/skater.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/test_scene.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/unlock_city.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/unlock_docks.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/unlock_mtzero.ms [new file with mode: 0644]
content_skaterift/metascenes/grave/unlock_valley.ms [new file with mode: 0644]
content_skaterift/metascenes/intro.ms [deleted file]
content_skaterift/metascenes/skater.ms
content_skaterift/metascenes/test_scene.ms [deleted file]
content_skaterift/metascenes/unlock_city.ms [deleted file]
content_skaterift/metascenes/unlock_docks.ms
content_skaterift/metascenes/unlock_mtzero.ms [deleted file]
content_skaterift/metascenes/unlock_valley.ms [deleted file]
content_skaterift/models/rk.mdl [new file with mode: 0644]
content_skaterift/sound/cs/rk.ogg [new file with mode: 0644]
shaders/model_character_view.fs
skaterift_blender/sr_main.py
skaterift_blender/sr_mat.py
skaterift_blender/sr_mdl.py
skaterift_blender/sr_metascene.py
src/2 [new file with mode: 0644]
src/ent_challenge.c
src/ent_challenge.h
src/ent_glider.c
src/ent_glider.h
src/ent_list.c
src/ent_npc.c
src/ent_npc.h
src/ent_objective.c
src/ent_objective.h
src/ent_region.c
src/ent_region.h
src/ent_relay.c
src/ent_relay.h
src/ent_route.c
src/ent_route.h
src/ent_script.c
src/ent_script.h
src/ent_skateshop.c
src/ent_skateshop.h
src/entity.c
src/entity.h
src/menu.c
src/metascene.c
src/metascene.h
src/model.c
src/player_glide.c
src/player_render.c
src/player_skate.c
src/player_walk.c
src/scripts/city.c
src/scripts/cutscene.c [new file with mode: 0644]
src/scripts/explode.c [new file with mode: 0644]
src/scripts/generic.c
src/scripts/hub.c
src/scripts/mtzero.c
src/scripts/tutorial_island.c
src/scripts/valley.c [new file with mode: 0644]
src/shader_props.h
src/skaterift.c
src/skaterift_script.c
src/skaterift_script.h
src/skeleton.h
src/world.h
src/world_entity.c
src/world_entity.h
src/world_gate.c
src/world_gate.h
src/world_load.c
src/world_render.c
src/world_routes.c
src/world_volumes.c
src/world_volumes.h
src/world_water.c
src/world_water.h

index 0282cadecbdbcc634c3065304d11222c7df4d9a7..d7beaab2ae1d29dfcada7e99639ad04af88f3863 100644 (file)
Binary files a/content_skaterift/maps/dev_tutorial/main.mdl and b/content_skaterift/maps/dev_tutorial/main.mdl differ
index 019bc06db9abad6afe528cc542015158655edd90..76975d95a43303024d5bb43dc6bdb5055ee2a64c 100644 (file)
Binary files a/content_skaterift/maps/mp_line1/main.mdl and b/content_skaterift/maps/mp_line1/main.mdl differ
index ca6fba16bc93e589911fc355be85423d98330d6d..940b7d6003359f760eb0bf5b78bdf1dfd96d3132 100644 (file)
Binary files a/content_skaterift/maps/mp_spawn/main.mdl and b/content_skaterift/maps/mp_spawn/main.mdl differ
diff --git a/content_skaterift/metascenes/battery_intro.ms b/content_skaterift/metascenes/battery_intro.ms
deleted file mode 100644 (file)
index 831d89c..0000000
Binary files a/content_skaterift/metascenes/battery_intro.ms and /dev/null differ
index dab0ebe2a4a4e476d8711309cc5cdb6fbccbf056..905d9452c30f023ec8c76eae81125221fa64a194 100644 (file)
Binary files a/content_skaterift/metascenes/ch1s2.ms and b/content_skaterift/metascenes/ch1s2.ms differ
diff --git a/content_skaterift/metascenes/ch1s3.ms b/content_skaterift/metascenes/ch1s3.ms
deleted file mode 100644 (file)
index 3d2576d..0000000
Binary files a/content_skaterift/metascenes/ch1s3.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch1s3b.ms b/content_skaterift/metascenes/ch1s3b.ms
deleted file mode 100644 (file)
index e760242..0000000
Binary files a/content_skaterift/metascenes/ch1s3b.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch1s4.ms b/content_skaterift/metascenes/ch1s4.ms
deleted file mode 100644 (file)
index 4a4901f..0000000
Binary files a/content_skaterift/metascenes/ch1s4.ms and /dev/null differ
index 5fa5f81b35385f0df573fc0a33905426ad6bc302..c390b8831d7f3a853bcf5d643d5986f427c50049 100644 (file)
Binary files a/content_skaterift/metascenes/ch1s5.ms and b/content_skaterift/metascenes/ch1s5.ms differ
diff --git a/content_skaterift/metascenes/ch1s6a.ms b/content_skaterift/metascenes/ch1s6a.ms
deleted file mode 100644 (file)
index cc1d3f0..0000000
Binary files a/content_skaterift/metascenes/ch1s6a.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch2e1.ms b/content_skaterift/metascenes/ch2e1.ms
deleted file mode 100644 (file)
index 5565ebf..0000000
Binary files a/content_skaterift/metascenes/ch2e1.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch2s1.ms b/content_skaterift/metascenes/ch2s1.ms
deleted file mode 100644 (file)
index 5fa2d0a..0000000
Binary files a/content_skaterift/metascenes/ch2s1.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch2s2.ms b/content_skaterift/metascenes/ch2s2.ms
deleted file mode 100644 (file)
index 43abc64..0000000
Binary files a/content_skaterift/metascenes/ch2s2.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch2s3a.ms b/content_skaterift/metascenes/ch2s3a.ms
deleted file mode 100644 (file)
index 66b50d5..0000000
Binary files a/content_skaterift/metascenes/ch2s3a.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch2s4.ms b/content_skaterift/metascenes/ch2s4.ms
deleted file mode 100644 (file)
index 8060b61..0000000
Binary files a/content_skaterift/metascenes/ch2s4.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch2s5.ms b/content_skaterift/metascenes/ch2s5.ms
deleted file mode 100644 (file)
index 063c7f7..0000000
Binary files a/content_skaterift/metascenes/ch2s5.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch2s6.ms b/content_skaterift/metascenes/ch2s6.ms
deleted file mode 100644 (file)
index 73ed57c..0000000
Binary files a/content_skaterift/metascenes/ch2s6.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch3s1.ms b/content_skaterift/metascenes/ch3s1.ms
deleted file mode 100644 (file)
index 2091c2c..0000000
Binary files a/content_skaterift/metascenes/ch3s1.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch3s2.ms b/content_skaterift/metascenes/ch3s2.ms
deleted file mode 100644 (file)
index 0990752..0000000
Binary files a/content_skaterift/metascenes/ch3s2.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch3s3.ms b/content_skaterift/metascenes/ch3s3.ms
deleted file mode 100644 (file)
index 2e1c064..0000000
Binary files a/content_skaterift/metascenes/ch3s3.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch4s1.ms b/content_skaterift/metascenes/ch4s1.ms
deleted file mode 100644 (file)
index 6e858e5..0000000
Binary files a/content_skaterift/metascenes/ch4s1.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch4s1a.ms b/content_skaterift/metascenes/ch4s1a.ms
deleted file mode 100644 (file)
index 221baff..0000000
Binary files a/content_skaterift/metascenes/ch4s1a.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch4s2.ms b/content_skaterift/metascenes/ch4s2.ms
deleted file mode 100644 (file)
index 031a3e9..0000000
Binary files a/content_skaterift/metascenes/ch4s2.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/ch4s3.ms b/content_skaterift/metascenes/ch4s3.ms
deleted file mode 100644 (file)
index 5fe7a9f..0000000
Binary files a/content_skaterift/metascenes/ch4s3.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/grave/battery_intro.ms b/content_skaterift/metascenes/grave/battery_intro.ms
new file mode 100644 (file)
index 0000000..831d89c
Binary files /dev/null and b/content_skaterift/metascenes/grave/battery_intro.ms differ
diff --git a/content_skaterift/metascenes/grave/ch1s2.ms b/content_skaterift/metascenes/grave/ch1s2.ms
new file mode 100644 (file)
index 0000000..dab0ebe
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch1s2.ms differ
diff --git a/content_skaterift/metascenes/grave/ch1s3.ms b/content_skaterift/metascenes/grave/ch1s3.ms
new file mode 100644 (file)
index 0000000..3d2576d
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch1s3.ms differ
diff --git a/content_skaterift/metascenes/grave/ch1s3b.ms b/content_skaterift/metascenes/grave/ch1s3b.ms
new file mode 100644 (file)
index 0000000..e760242
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch1s3b.ms differ
diff --git a/content_skaterift/metascenes/grave/ch1s4.ms b/content_skaterift/metascenes/grave/ch1s4.ms
new file mode 100644 (file)
index 0000000..4a4901f
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch1s4.ms differ
diff --git a/content_skaterift/metascenes/grave/ch1s5.ms b/content_skaterift/metascenes/grave/ch1s5.ms
new file mode 100644 (file)
index 0000000..5fa5f81
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch1s5.ms differ
diff --git a/content_skaterift/metascenes/grave/ch1s6a.ms b/content_skaterift/metascenes/grave/ch1s6a.ms
new file mode 100644 (file)
index 0000000..58ee0bf
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch1s6a.ms differ
diff --git a/content_skaterift/metascenes/grave/ch2e1.ms b/content_skaterift/metascenes/grave/ch2e1.ms
new file mode 100644 (file)
index 0000000..5565ebf
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch2e1.ms differ
diff --git a/content_skaterift/metascenes/grave/ch2s1.ms b/content_skaterift/metascenes/grave/ch2s1.ms
new file mode 100644 (file)
index 0000000..5fa2d0a
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch2s1.ms differ
diff --git a/content_skaterift/metascenes/grave/ch2s2.ms b/content_skaterift/metascenes/grave/ch2s2.ms
new file mode 100644 (file)
index 0000000..43abc64
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch2s2.ms differ
diff --git a/content_skaterift/metascenes/grave/ch2s3a.ms b/content_skaterift/metascenes/grave/ch2s3a.ms
new file mode 100644 (file)
index 0000000..66b50d5
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch2s3a.ms differ
diff --git a/content_skaterift/metascenes/grave/ch2s4.ms b/content_skaterift/metascenes/grave/ch2s4.ms
new file mode 100644 (file)
index 0000000..8060b61
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch2s4.ms differ
diff --git a/content_skaterift/metascenes/grave/ch2s5.ms b/content_skaterift/metascenes/grave/ch2s5.ms
new file mode 100644 (file)
index 0000000..063c7f7
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch2s5.ms differ
diff --git a/content_skaterift/metascenes/grave/ch2s6.ms b/content_skaterift/metascenes/grave/ch2s6.ms
new file mode 100644 (file)
index 0000000..73ed57c
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch2s6.ms differ
diff --git a/content_skaterift/metascenes/grave/ch3s1.ms b/content_skaterift/metascenes/grave/ch3s1.ms
new file mode 100644 (file)
index 0000000..2091c2c
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch3s1.ms differ
diff --git a/content_skaterift/metascenes/grave/ch3s2.ms b/content_skaterift/metascenes/grave/ch3s2.ms
new file mode 100644 (file)
index 0000000..0990752
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch3s2.ms differ
diff --git a/content_skaterift/metascenes/grave/ch3s3.ms b/content_skaterift/metascenes/grave/ch3s3.ms
new file mode 100644 (file)
index 0000000..2e1c064
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch3s3.ms differ
diff --git a/content_skaterift/metascenes/grave/ch4rk.ms b/content_skaterift/metascenes/grave/ch4rk.ms
new file mode 100644 (file)
index 0000000..d2c4efe
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch4rk.ms differ
diff --git a/content_skaterift/metascenes/grave/ch4s1.ms b/content_skaterift/metascenes/grave/ch4s1.ms
new file mode 100644 (file)
index 0000000..6e858e5
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch4s1.ms differ
diff --git a/content_skaterift/metascenes/grave/ch4s1a.ms b/content_skaterift/metascenes/grave/ch4s1a.ms
new file mode 100644 (file)
index 0000000..eb38e45
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch4s1a.ms differ
diff --git a/content_skaterift/metascenes/grave/ch4s2.ms b/content_skaterift/metascenes/grave/ch4s2.ms
new file mode 100644 (file)
index 0000000..8b4ccf3
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch4s2.ms differ
diff --git a/content_skaterift/metascenes/grave/ch4s3.ms b/content_skaterift/metascenes/grave/ch4s3.ms
new file mode 100644 (file)
index 0000000..5fe7a9f
Binary files /dev/null and b/content_skaterift/metascenes/grave/ch4s3.ms differ
diff --git a/content_skaterift/metascenes/grave/intro.ms b/content_skaterift/metascenes/grave/intro.ms
new file mode 100644 (file)
index 0000000..3488977
Binary files /dev/null and b/content_skaterift/metascenes/grave/intro.ms differ
diff --git a/content_skaterift/metascenes/grave/skater.ms b/content_skaterift/metascenes/grave/skater.ms
new file mode 100644 (file)
index 0000000..fab3de8
Binary files /dev/null and b/content_skaterift/metascenes/grave/skater.ms differ
diff --git a/content_skaterift/metascenes/grave/test_scene.ms b/content_skaterift/metascenes/grave/test_scene.ms
new file mode 100644 (file)
index 0000000..b5c5c1f
Binary files /dev/null and b/content_skaterift/metascenes/grave/test_scene.ms differ
diff --git a/content_skaterift/metascenes/grave/unlock_city.ms b/content_skaterift/metascenes/grave/unlock_city.ms
new file mode 100644 (file)
index 0000000..001e689
Binary files /dev/null and b/content_skaterift/metascenes/grave/unlock_city.ms differ
diff --git a/content_skaterift/metascenes/grave/unlock_docks.ms b/content_skaterift/metascenes/grave/unlock_docks.ms
new file mode 100644 (file)
index 0000000..9e29743
Binary files /dev/null and b/content_skaterift/metascenes/grave/unlock_docks.ms differ
diff --git a/content_skaterift/metascenes/grave/unlock_mtzero.ms b/content_skaterift/metascenes/grave/unlock_mtzero.ms
new file mode 100644 (file)
index 0000000..c61668e
Binary files /dev/null and b/content_skaterift/metascenes/grave/unlock_mtzero.ms differ
diff --git a/content_skaterift/metascenes/grave/unlock_valley.ms b/content_skaterift/metascenes/grave/unlock_valley.ms
new file mode 100644 (file)
index 0000000..77285f1
Binary files /dev/null and b/content_skaterift/metascenes/grave/unlock_valley.ms differ
diff --git a/content_skaterift/metascenes/intro.ms b/content_skaterift/metascenes/intro.ms
deleted file mode 100644 (file)
index 3488977..0000000
Binary files a/content_skaterift/metascenes/intro.ms and /dev/null differ
index fab3de868cb4b332f4f7575fb9451dff6b4fa100..6f24ae1c7d25ca49c4f295da2a38e1bfc79a821b 100644 (file)
Binary files a/content_skaterift/metascenes/skater.ms and b/content_skaterift/metascenes/skater.ms differ
diff --git a/content_skaterift/metascenes/test_scene.ms b/content_skaterift/metascenes/test_scene.ms
deleted file mode 100644 (file)
index b5c5c1f..0000000
Binary files a/content_skaterift/metascenes/test_scene.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/unlock_city.ms b/content_skaterift/metascenes/unlock_city.ms
deleted file mode 100644 (file)
index 001e689..0000000
Binary files a/content_skaterift/metascenes/unlock_city.ms and /dev/null differ
index 9e29743bdf6fd8d0ed1c30a1b00e5ab70bb4bd41..b9455cf543317874b9c1775bc8e26bc0390e8c33 100644 (file)
Binary files a/content_skaterift/metascenes/unlock_docks.ms and b/content_skaterift/metascenes/unlock_docks.ms differ
diff --git a/content_skaterift/metascenes/unlock_mtzero.ms b/content_skaterift/metascenes/unlock_mtzero.ms
deleted file mode 100644 (file)
index c61668e..0000000
Binary files a/content_skaterift/metascenes/unlock_mtzero.ms and /dev/null differ
diff --git a/content_skaterift/metascenes/unlock_valley.ms b/content_skaterift/metascenes/unlock_valley.ms
deleted file mode 100644 (file)
index 77285f1..0000000
Binary files a/content_skaterift/metascenes/unlock_valley.ms and /dev/null differ
diff --git a/content_skaterift/models/rk.mdl b/content_skaterift/models/rk.mdl
new file mode 100644 (file)
index 0000000..92a2727
Binary files /dev/null and b/content_skaterift/models/rk.mdl differ
diff --git a/content_skaterift/sound/cs/rk.ogg b/content_skaterift/sound/cs/rk.ogg
new file mode 100644 (file)
index 0000000..933f4d6
Binary files /dev/null and b/content_skaterift/sound/cs/rk.ogg differ
index 502d67299d95d95c87dc6ff96393447928608694..42fadcbec8f7f489f087f7568d15891836c14142 100644 (file)
@@ -1,5 +1,6 @@
 uniform sampler2D uTexMain;
 uniform vec3 uCamera;
+uniform int uShadeless;
 
 in vec4 aColour;
 in vec2 aUv;
@@ -16,23 +17,16 @@ vec3 character_clearskies_lighting( vec3 normal, float shadow, vec3 halfview )
 {
    float fresnel = 1.0 - abs(dot(normal,halfview));
 
-   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, 
-                               g_sunset_phase );
-
-
+   vec3  reflect_colour = mix( g_daysky_colour.rgb, g_sunset_colour.rgb, g_sunset_phase );
    vec3  sky_reflection = 0.5 * fresnel * reflect_colour;
-   vec3  light_sun      = max(0.0, dot(normal,g_sun_dir.xyz)*0.5+0.5) 
-                           * g_sun_colour.rgb * g_day_phase;
+   vec3  light_sun      = max(0.0, dot(normal,g_sun_dir.xyz)*0.5+0.5) * g_sun_colour.rgb * g_day_phase;
 
    float scaled_shadow = max( shadow, 1.0 - max(g_sun_dir.y,0.0) );
-   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, 
-                       g_sunset_phase );
-
+   vec3 ambient = mix( g_ambient_colour.rgb, g_sunset_ambient.rgb, g_sunset_phase );
    return ambient + (light_sun + sky_reflection) * shadow;
 }
 
-vec3 character_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,
-                                 float light_mask )
+vec3 character_compute_lighting( vec3 diffuse, vec3 normal, vec3 co, float light_mask )
 {
    if( g_light_preview == 1 )
       diffuse = vec3(0.75);
@@ -42,11 +36,8 @@ vec3 character_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,
    float fdist = length(halfview);
    halfview /= fdist;
 
-   float world_shadow = newlight_compute_sun_shadow( 
-               co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );
-
-   vec3 total_light = character_clearskies_lighting( 
-                           normal, min( light_mask, world_shadow ), halfview );
+   float world_shadow = newlight_compute_sun_shadow( co, g_sun_dir.xyz * (1.0/(max(g_sun_dir.y,0.0)+0.2)) );
+   vec3 total_light = character_clearskies_lighting( normal, min( light_mask, world_shadow ), halfview );
 
    vec3 cube_coord = (co - g_cube_min.xyz) * g_cube_inv_range.xyz;
         cube_coord = floor( cube_coord );
@@ -70,14 +61,8 @@ vec3 character_compute_lighting( vec3 diffuse, vec3 normal, vec3 co,
    ivec3 coord = ivec3( cube_coord );
    uvec4 index_sample = texelFetch( uLightsIndex, coord, 0 );
 
-   total_light += 
-      scene_calculate_packed_light_patch( index_sample.x,
-                                          halfview, co, normal ) 
-                                          * light_mask;
-   total_light += 
-      scene_calculate_packed_light_patch( index_sample.y,
-                                          halfview, co, normal )
-                                          * light_mask;
+   total_light += scene_calculate_packed_light_patch( index_sample.x, halfview, co, normal ) * light_mask;
+   total_light += scene_calculate_packed_light_patch( index_sample.y, halfview, co, normal ) * light_mask;
 
    // Take a section of the sky function to give us a matching fog colour
 
@@ -101,6 +86,9 @@ void main(){
    vec3 diffuse   = texture( uTexMain, aUv ).rgb;
    vec3 composite = character_compute_lighting( diffuse, qnorm, aWorldCo, 1.0 );
 
+   if( uShadeless == 1 )
+      composite = diffuse;
+
    float dist    = distance( aWorldCo, uCamera ) - 0.08;
    float opacity = clamp( dist*dist, 0.0, 1.0 );
 
index 0aca2e13f13c602d87ad33ed5c3a6954eca316d1..33461958b219dbba611ddd22b265bc61ec4148da 100644 (file)
@@ -30,7 +30,7 @@ sr_entity_list = [
    ('ent_ccmd',         'CCmd',           '', 17 ),
    ('ent_objective',    'Objective',      '', 18 ),
    ('ent_challenge',    'Challenge',      '', 19 ),
-   ('ent_relay',        'Relay',          '', 20 ),
+   ('ent_relay',        'DELETED0',       '', 20 ),
    # reserved 21.. cubemap.
    ('ent_miniworld',    'Mini World',     '', 22 ),
    ('ent_prop',         'Prop',           '', 23 ),
@@ -39,14 +39,15 @@ sr_entity_list = [
    ('ent_glider',       'Glider',         '', 26 ),
    ('ent_npc',          'npc',            '', 27 ),
    # reserved 28.. armature
-   ('ent_script',       'Script',         '', 29 )
+   ('ent_script',       'Script',         '', 29 ),
+   ('ent_cutscene',     'Cutscene',       '', 30 ),
 ]
 
 MDL_VERSION_NR = 109
 SR_TRIGGERABLE = [ 'ent_audio', 'ent_ccmd', 'ent_gate', 'ent_challenge', \
                    'ent_relay', 'ent_skateshop', 'ent_objective', 'ent_route',\
                    'ent_miniworld', 'ent_region', 'ent_glider', 'ent_list',\
-                   'ent_npc', 'ent_water', 'ent_script' ]
+                   'ent_npc', 'ent_water' ]
 
 def get_entity_enum_id( alias ):
 #{
@@ -177,6 +178,27 @@ class mdl_texture(Structure):
                ("glname",c_uint32)]
 #}
 
+class ent_event_data_union(Union):
+#{
+   _fields_ = [("const_i32",c_int32),
+              ("const_f32",c_float),
+              ("const_entity_id",c_uint32),
+              ("const_pstr",c_uint32),
+              ("pstr_data_alias",c_uint32)]
+#}
+
+class ent_event(Structure):
+#{
+   _fields_ = [("pstr_source_event",c_uint32),
+               ("pstr_recieve_event",c_uint32),
+               ("source_entity_id",c_uint32),
+               ("recieve_entity_id",c_uint32),
+               ("flags",c_uint32),
+               ("delay",c_float),
+               ("unused0",c_uint32),
+               ("data", ent_event_data_union )]
+#}
+
 class ent_spawn(Structure):
 #{
    _fields_ = [("transform",mdl_transform),
@@ -219,7 +241,7 @@ class ent_gate(Structure):
                ("submesh_start",c_uint32), # v102+ 
                ("submesh_count",c_uint32), # v102+ (can be 0)
                ]
-   sr_functions = { 0: 'unlock' }
+   sr_functions = { 'lock': 0x1 }
 #}
 
 class ent_route_node(Structure):
@@ -266,7 +288,7 @@ class ent_list(Structure):
 # used in ent_list
 class file_entity_ref(Structure):
 #{
-   _fields_ = [("entity_id",c_uint32)]
+   _fields_ = [("entity_id",c_uint32),("pstr_alias",c_uint32)]
 #}
 
 class ent_checkpoint(Structure):
@@ -291,22 +313,30 @@ class ent_route(Structure):
                ("id_camera",c_uint32), # v103+ 
                ]
 
-   sr_functions = { 0: 'view' }
+   sr_functions = { 'view': 0x00 }
 #}
 
-class ent_glider(Structure):#{
+class ent_glider(Structure):
+#{
    _fields_ = [("transform",mdl_transform),
                ("flags",c_uint32),
                ("cooldown",c_float)]
-   sr_functions = { 0: 'unlock',
-                    1: 'equip' }
+   sr_functions = { 'lock': 0x1, 'equip': 0x00 }
 #}
 
-class ent_npc(Structure):#{
+class ent_npc(Structure):
+#{
    _fields_ = [("transform",mdl_transform),
                ("pstr_id",c_uint32),
                ("pstr_context_id",c_uint32)]
-   sr_functions = { 1: 'proximity', 0: 'interact', -1: 'unproximity' }
+   sr_functions = { 'proximity': 0x00, 'interact': 0x00 }
+#}
+
+class ent_script(Structure):
+#{
+   _fields_ = [("pstr_script_name",c_uint32),
+               ("deleted0",c_uint32),
+               ("flags",c_uint32)]
 #}
 
 class ent_water(Structure):
@@ -315,13 +345,13 @@ class ent_water(Structure):
                ("max_dist",c_float),
                ("reserved0",c_uint32),
                ("reserved1",c_uint32)]
-   sr_functions = { 0: "drown" }
+   sr_functions = { 'drown': 0x00 }
 #}
 
 class volume_trigger(Structure):
 #{
-   _fields_ = [("event",c_uint32),
-               ("event_leave",c_int32)]
+   _fields_ = [("blank",c_uint32),
+               ("blank2",c_int32)]
 #}
 
 class volume_particles(Structure):
@@ -332,7 +362,7 @@ class volume_particles(Structure):
 
 class volume_interact(Structure):
 #{
-   _fields_ = [("event",c_uint32),
+   _fields_ = [("blank",c_uint32),
                ("pstr_text",c_int32)]
 #}
 
@@ -349,7 +379,7 @@ class ent_volume(Structure):
                ("to_world",(c_float*3)*4),
                ("to_local",(c_float*3)*4),
                ("flags",c_uint32),
-               ("target",c_uint32),
+               ("deleted0",c_uint32),
                ("_anon",volume_union)]
 #}
 
@@ -365,6 +395,7 @@ class ent_audio(Structure):
                ("group",c_uint32),
                ("probability_curve",c_uint32),
                ("max_channels",c_uint32)]
+   sr_functions = { 'play': 0x00, 'spawn_particle': 0x00 }
 #}
 
 class ent_marker(Structure):
@@ -444,8 +475,7 @@ class ent_skateshop(Structure):
    _fields_ = [("transform",mdl_transform), ("type",c_uint32),
                ("id_camera",c_uint32), 
                ("_anonymous_union",ent_skateshop_anon_union)]
-
-   sr_functions = { 0: 'view', -1: 'unview' }
+   sr_functions = { 'open': 0x00 }
 #}
 
 class ent_swspreview(Structure):
@@ -457,8 +487,7 @@ class ent_swspreview(Structure):
 
 class ent_camera(Structure):
 #{
-   _fields_ = [("co",c_float*3),("r",c_float*3),
-               ("fov",c_float)]
+   _fields_ = [("co",c_float*3),("r",c_float*3),("fov",c_float)]
 #}
 
 class ent_worldinfo(Structure):
@@ -475,17 +504,11 @@ class ent_worldinfo(Structure):
 class ent_ccmd(Structure):
 #{
    _fields_ = [("pstr_command",c_uint32)]
+   sr_functions = { 'exec': 0x00 }
 #}
 
-class ent_script(Structure):
+class ent_objective(Structure):
 #{
-   _fields_ = [("pstr_script_name",c_uint32),
-               ("entity_list_id",c_uint32),
-               ("flags",c_uint32)]
-#}
-
-
-class ent_objective(Structure):#{
    _fields_ = [("transform",mdl_transform),
                ("submesh_start",c_uint32), ("submesh_count",c_uint32),
                ("flags",c_uint32),
@@ -495,27 +518,23 @@ class ent_objective(Structure):#{
                ("deleted1",c_int32),
                ("time_limit",c_float),
                ("pstr_description_ui",c_uint32)]
-
-   sr_functions = { 0: 'trigger',
-                    2: 'show',
-                    3: 'hide' }
+   sr_functions = { 'trigger': 0x00, 'visibility': 0x1 }
 #}
 
-class ent_challenge(Structure):#{
+class ent_challenge(Structure):
+#{
    _fields_ = [("transform",mdl_transform),
                ("pstr_alias",c_uint32),
                ("flags",c_uint32),
-               ("on_activate_id",c_uint32),
-               ("on_activate_event",c_int32),
-               ("on_complete_id",c_uint32),
-               ("on_complete_event",c_int32),
+               ("deleted0",c_uint32),
+               ("deleted1",c_int32),
+               ("deleted2",c_uint32),
+               ("deleted3",c_int32),
                ("first_objective_id",c_uint32),
                ("camera_id",c_uint32),
                ("status",c_uint32),
                ("reset_spawn_id",c_uint32)]
-   sr_functions = { 0: 'win',
-                    1: 'view',
-                   -1: 'unview' }
+   sr_functions = { 'win': 0x00, 'view': 0x00 }
 #}
 
 class ent_region(Structure):#{
@@ -525,17 +544,12 @@ class ent_region(Structure):#{
                ("flags",c_uint32),
                ("list_id",c_uint32),
                #105+
-               ("target0",c_uint32*2)]
-   sr_functions = { 0: 'enter', 1: 'leave' }
+               ("deleted01",c_uint32*2)]
+   sr_functions = { 'set_active': 0x00 }
 #}
 
-class ent_relay(Structure):#{
-   _fields_ = [("targets",(c_uint32*2)*4),
-               ("targets_events",c_int32*4)]
-   sr_functions = { 0: 'trigger' }
-#}
-
-class ent_cubemap(Structure):#{
+class ent_cubemap(Structure):
+#{
    _fields_ = [("co",c_float*3),
                ("resolution",c_uint32), #placeholder
                ("live",c_uint32),       #placeholder
@@ -545,16 +559,8 @@ class ent_cubemap(Structure):#{
                ("placeholder",c_uint32*2)]
 #}
 
-class ent_miniworld(Structure):#{
-   _fields_ = [("transform",mdl_transform),
-               ("pstr_world",c_uint32),
-               ("camera",c_uint32),
-               ("proxy",c_uint32)]
-
-   sr_functions = { 0: 'zone', 1: 'leave' }
-#}
-
-class ent_prop(Structure):#{
+class ent_prop(Structure):
+#{
    _fields_ = [("transform",mdl_transform),
                ("submesh_start",c_uint32),
                ("submesh_count",c_uint32),
@@ -564,12 +570,12 @@ class ent_prop(Structure):#{
 
 def sr_filter_ent_type( obj, ent_types ):
 #{
-   if obj == bpy.context.active_object: return False
+   if obj == bpy.context.active_object: return False
 
    for c0 in obj.users_collection:#{
       for c1 in bpy.context.active_object.users_collection:#{
          if c0 == c1:#{
-            return  obj_ent_type( obj ) in ent_types
+            return (ent_types == None) or (obj_ent_type( obj ) in ent_types)
          #}
       #}
    #}
@@ -1051,28 +1057,104 @@ class SR_INTERFACE(bpy.types.Panel):
                   F'bpy.types.Light["{active_object.data.name}"].SR_data', \
                   [active_object.data.SR_data] )
          #}
-         elif active_object.type in ['EMPTY','CURVE','MESH']:#{
+         elif active_object.type in ['EMPTY','CURVE','MESH']:
+         #{
             box.prop( active_object.SR_data, "ent_type" )
             ent_type = active_object.SR_data.ent_type
             
             col = getattr( active_object.SR_data, ent_type, None )
             if col != None and len(col)!=0: 
-               _draw_prop_collection( \
-         F'bpy.types.Object["{active_object.name}"].SR_data.{ent_type}[0]', \
-         col )
+               _draw_prop_collection( F'bpy.types.Object["{active_object.name}"].SR_data.{ent_type}[0]', col )
 
             if active_object.type == 'MESH':#{
                col = getattr( active_object.data.SR_data, ent_type, None )
                if col != None and len(col)!=0: 
-                  _draw_prop_collection( \
-         F'bpy.types.Mesh["{active_object.data.name}"].SR_data.{ent_type}[0]', \
-         col )
+                  _draw_prop_collection( F'bpy.types.Mesh["{active_object.data.name}"].SR_data.{ent_type}[0]', col )
+            #}
+         #}
+      #}
+   #}
+#}
+
+class SR_MARKER_PANEL(bpy.types.Panel):
+#{
+   bl_idname = "DOPESHEET_EDITOR_PT_skate_rift"
+   bl_label = "Skate Rift"
+   bl_space_type = 'DOPESHEET_EDITOR'
+   bl_region_type = 'UI'
+   bl_category = "Skate Rift"
+
+   def draw(_, context):
+   #{
+      markers = context.scene.timeline_markers
+      if markers:
+      #{
+         for tlm in markers:
+         #{
+            if tlm.select:
+            #{
+               box = _.layout.box()
+               box.label( text=F'Selected Marker: {tlm.name}' )
+               
+               data = tlm.SR_data
+               box.prop( data, 'tipo' )
+
+               if data.tipo == '1':
+                  box.prop( data, 'event_string' )
+
+               if data.tipo == '2':
+               #{
+                  box.prop( data, 'subtitle_person' )
+                  box.prop( data, 'subtitle_en' )
+
+                  length = 0
+                  for j in range(len(data.subtitle_en)-1):
+                  #{
+                     if data.subtitle_en[j:j+2] == '\\n':
+                        length = -1
+                     else:
+                        length += 1
+
+                     if length > 50:
+                     #{
+                        box.label( text='Warning, line too long!' )
+                        break
+                     #}
+                  #}
+               #}
             #}
          #}
       #}
    #}
 #}
 
+class SR_ENTITY_PANEL(bpy.types.Panel):
+#{
+   bl_label="Skate Rift Entity"
+   bl_idname="OBJECT_PT_sr_entity"
+   bl_space_type='PROPERTIES'
+   bl_region_type='WINDOW'
+   bl_context="object"
+   
+   def draw(_,context):
+   #{
+      active_object = bpy.context.active_object
+      if active_object == None: return
+
+      box = _.layout.box()
+      row = box.row()
+      row.alignment = 'CENTER'
+      row.label( text="Outputs" )
+      row.scale_y = 1.5
+      box.template_list('SR_UL_ENT_EVENT_LIST', 'Outputs', active_object.SR_data, 'events', \
+                         active_object.SR_data, 'events_index', rows=5)
+
+      row = box.row()
+      row.operator( 'skaterift.ent_event_new_entry', text='Add' )
+      row.operator( 'skaterift.ent_event_del_entry', text='Remove' )
+   #}
+#}
+
 class SR_MATERIAL_PANEL(bpy.types.Panel):
 #{
    bl_label="Skate Rift material"
@@ -1100,6 +1182,7 @@ class SR_MATERIAL_PANEL(bpy.types.Panel):
 
       _.layout.prop( active_mat.SR_data, "shader" )
       _.layout.prop( active_mat.SR_data, "surface_prop" )
+      _.layout.prop( active_mat.SR_data, "additive" )
       _.layout.prop( active_mat.SR_data, "collision" )
 
       if active_mat.SR_data.collision:#{
@@ -1621,15 +1704,23 @@ class SR_OT_ENT_LIST_DEL_ITEM(bpy.types.Operator):#{
 
 class SR_OBJECT_ENT_LIST_ENTRY(bpy.types.PropertyGroup):
 #{
-   target: bpy.props.PointerProperty( \
-               type=bpy.types.Object, name='target' )
+   target: bpy.props.PointerProperty( type=bpy.types.Object, name='target' )
+   alias: bpy.props.StringProperty( name='alias' )
 #}
 
 class SR_UL_ENT_LIST(bpy.types.UIList):#{
    bl_idname = 'SR_UL_ENT_LIST'
 
    def draw_item(_,context,layout,data,item,icon,active_data,active_propname):#{
-      layout.prop( item, 'target', text='', emboss=False )
+      s0 = layout.split(factor=0.22)
+      c = s0.column()
+      c.prop( item, 'alias', text='', emboss=True )
+      c = s0.column()
+      s1 = c.split( factor=0.7 )
+      c = s1.column()
+      c.prop( item, 'target', text='', emboss=False )
+      c = s1.column()
+      c.label( text=item.target.SR_data.ent_type if item.target else '' )
    #}
 #}
 
@@ -1702,41 +1793,41 @@ class SR_OBJECT_ENT_VOLUME(bpy.types.PropertyGroup):#{
    water_volume: bpy.props.BoolProperty( name="Water Volume" )
    text: bpy.props.StringProperty()
 
-   @staticmethod
-   def inspect_target( layout, data, propname, evs = ['_event'], text='' ):#{
-      box = layout.box()
-      box.prop( data[0], propname, text=text )
-
-      for evname in evs:#{
-         row = box.row()
-         row.prop( data[0], propname + evname )
-
-         target = getattr( data[0], propname )
-         if target:#{
-            tipo = target.SR_data.ent_type
-            cls = globals()[ tipo ]
-
-            table = getattr( cls, 'sr_functions', None )
-            if table:#{
-               index = getattr( data[0], propname + evname )
-               if index in table:
-                  row.label( text=table[index] )
-               else:
-                  row.label( text="undefined function" )
-            #}
-         #}
-         else:#{
-            row.label( text="..." )
-            row.enabled=False
-         #}
-      #}
-   #}
+   @staticmethod
+   def inspect_target( layout, data, propname, evs = ['_event'], text='' ):#{
+      box = layout.box()
+      box.prop( data[0], propname, text=text )
+
+      for evname in evs:#{
+         row = box.row()
+         row.prop( data[0], propname + evname )
+
+         target = getattr( data[0], propname )
+         if target:#{
+            tipo = target.SR_data.ent_type
+            cls = globals()[ tipo ]
+
+            table = getattr( cls, 'sr_functions', None )
+            if table:#{
+               index = getattr( data[0], propname + evname )
+               if index in table:
+                  row.label( text=table[index] )
+               else:
+                  row.label( text="undefined function" )
+            #}
+         #}
+         else:#{
+            row.label( text="..." )
+            row.enabled=False
+         #}
+      #}
+   # #}
 
    @staticmethod
    def sr_inspector( layout, data ):
    #{
       layout.prop( data[0], 'subtype' )
-      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target', ['_event','_event_leave'] )
+      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target', ['_event','_event_leave'] )
       if data[0].subtype == '2':
       #{
          layout.prop( data[0], 'text' )
@@ -1813,8 +1904,7 @@ class SR_OBJECT_ENT_AUDIO(bpy.types.PropertyGroup):
       c.label( text='Filepath' )
       c = split.column()
       c.label( text='Chance' )
-      layout.template_list('SR_UL_AUDIO_LIST', 'Files', \
-                            data[0], 'files', data[0], 'files_index', rows=5)
+      layout.template_list('SR_UL_AUDIO_LIST', 'Files', data[0], 'files', data[0], 'files_index', rows=5)
 
       row = layout.row()
       row.operator( 'skaterift.al_new_entry', text='Add' )
@@ -1967,10 +2057,14 @@ class SR_OBJECT_ENT_OBJECTIVE(bpy.types.PropertyGroup):#{
    proxima: bpy.props.PointerProperty( \
             type=bpy.types.Object, name="Next", \
             poll=lambda self,obj: sr_filter_ent_type(obj,['ent_objective']))
+
+   ################### DELETED ##############
    target: bpy.props.PointerProperty( \
            type=bpy.types.Object, name="Win", \
            poll=lambda self,obj: sr_filter_ent_type(obj,SR_TRIGGERABLE))
    target_event: bpy.props.IntProperty( name="Event/Method" )
+   ################### DELETED ##############
+
    time_limit: bpy.props.FloatProperty( name="Time Limit", default=1.0 )
    filtrar: bpy.props.EnumProperty( name='Filter',\
       items=[('0','none',''),
@@ -1986,11 +2080,13 @@ class SR_OBJECT_ENT_OBJECTIVE(bpy.types.PropertyGroup):#{
              (str(0x20|0x40),'grind_any',''),
              (str(0x80),'footplant',''),
              (str(0x100),'passthrough',''),
+             (str(0x200),'glider',''),
              ])
    description: bpy.props.StringProperty( name="UI Description" )
 
    @staticmethod
-   def sr_inspector( layout, data ):#{
+   def sr_inspector( layout, data ):
+   #{
       layout.prop( data[0], 'proxima' )
       layout.prop( data[0], 'time_limit' )
       layout.prop( data[0], 'filtrar' )
@@ -2014,6 +2110,7 @@ class SR_OBJECT_ENT_CHALLENGE(bpy.types.PropertyGroup):#{
 
    time_limit: bpy.props.BoolProperty( name="Time Limit" )
    is_story: bpy.props.BoolProperty( name="Is story event" )
+   any_order: bpy.props.BoolProperty( name="Any order allowed" )
 
    first: bpy.props.PointerProperty( \
             type=bpy.types.Object, name="First Objective", \
@@ -2040,9 +2137,10 @@ class SR_OBJECT_ENT_CHALLENGE(bpy.types.PropertyGroup):#{
       layout.prop( data[0], 'first', text=("First Objective") )
       layout.prop( data[0], 'reset_spawn' )
       layout.prop( data[0], 'time_limit' )
+      layout.prop( data[0], 'any_order' )
       # layout.prop( data[0], 'is_story' )
-      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target', text="On Activate" )
-      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'complete', text="On Complete" )
+      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target', text="On Activate" )
+      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'complete', text="On Complete" )
    #}
 #}
 
@@ -2061,7 +2159,7 @@ class SR_OBJECT_ENT_REGION(bpy.types.PropertyGroup):#{
    def sr_inspector( layout, data ):#{
       layout.prop( data[0], 'title' )
       layout.prop( data[0], 'zone_volume' )
-      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target0' )
+      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target0' )
    #}
 #}
 
@@ -2083,23 +2181,173 @@ class SR_OBJECT_ENT_RELAY(bpy.types.PropertyGroup):#{
    target1_event: bpy.props.IntProperty( name="Event" )
    target2_event: bpy.props.IntProperty( name="Event" )
    target3_event: bpy.props.IntProperty( name="Event" )
-
-   @staticmethod
-   def sr_inspector( layout, data ):#{
-      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target0' )
-      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target1' )
-      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target2' )
-      SR_OBJECT_ENT_VOLUME.inspect_target( layout, data, 'target3' )
-   #}
 #}
 
 class SR_OBJECT_ENT_SCRIPT(bpy.types.PropertyGroup):
 #{
    script_alias: bpy.props.StringProperty( name="Script alias" )
    flags: bpy.props.IntProperty( name="Flags" )
-   entity_list: bpy.props.PointerProperty( \
-            type=bpy.types.Object, name="Entity List", \
-            poll=lambda self,obj: sr_filter_ent_type(obj,['ent_list']))
+
+   #entity_list: bpy.props.PointerProperty( \
+   #         type=bpy.types.Object, name="Entity List", \
+   #         poll=lambda self,obj: sr_filter_ent_type(obj,['ent_list']))
+#}
+
+class SR_OBJECT_ENT_LOGIC(bpy.types.PropertyGroup):
+#{
+   tipo: bpy.props.EnumProperty( name='Type',\
+      items=[(str(0x10),'AND',''),
+             (str(0x20),'NOT',''),
+             (str(0x40),'OR',''),
+             (str(0x100),'ATOM EQ STR',''),
+             #(str(0x200),'ATOM EQ INT',''),
+             (str(0x1000),'RISING TRIGGER',''),
+             ])
+
+   atom_alias: bpy.props.StringProperty( name="Atom Alias" )
+   atom_enum_value: bpy.props.StringProperty( name="Atom Enum Value" )
+
+   source_entity: bpy.props.PointerProperty( type=bpy.types.Object, name="Source Entity", \
+                                             poll=lambda self,obj: sr_filter_ent_type(obj,['ent_list','ent_logic']))
+
+   @staticmethod
+   def sr_inspector( layout, data ):
+   #{
+      data = data[0]
+      layout.prop( data, 'tipo' )
+      tipo = int( data.tipo )
+
+      if (tipo & (0x10|0x20|0x40|0x1000)) > 0:
+      #{
+         layout.prop( data, 'source_entity' )
+      #}
+
+      if (tipo & (0x100|0x200)):
+      #{
+         box = layout.box()
+         box.prop( data, 'atom_alias', text='Atom Alias' )
+
+         if tipo == 0x100:
+            box.prop( data, 'atom_enum_value', text='EQ' )
+      #}
+   #}
+#}
+
+class SR_OT_ENT_EVENT_NEW_ITEM(bpy.types.Operator):
+#{
+   bl_idname = "skaterift.ent_event_new_entry"
+   bl_label = "Add event"
+   
+   def execute(self, context):
+   #{
+      active_object = context.active_object
+      active_object.SR_data.events.add()
+      return{'FINISHED'}
+   #}
+#}
+
+class SR_OT_ENT_EVENT_DEL_ITEM(bpy.types.Operator):
+#{
+   bl_idname = "skaterift.ent_event_del_entry"
+   bl_label = "Remove event"
+
+   @classmethod 
+   def poll(cls, context):
+   #{
+      return context.active_object.SR_data.events
+   #}
+   
+   def execute(self, context):
+   #{
+      data = context.active_object.SR_data
+      data.events.remove( data.events_index )
+      data.events_index = min(max(0,data.events_index-1), len(data.events)-1)
+      return{'FINISHED'}
+   #}
+#}
+
+class SR_OBJECT_ENT_EVENT_ENTRY(bpy.types.PropertyGroup):
+#{
+   reciever: bpy.props.PointerProperty( type=bpy.types.Object, name='target', \
+                                        poll=lambda self,obj: sr_filter_ent_type(obj,None) )
+   source_event: bpy.props.StringProperty()
+   reciever_event: bpy.props.StringProperty()
+   delay: bpy.props.FloatProperty()
+
+   arg_string: bpy.props.StringProperty()
+   arg_entity: bpy.props.PointerProperty( type=bpy.types.Object, name='target', \
+                                          poll=lambda self,obj: sr_filter_ent_type(obj,None) )
+   arg_float: bpy.props.FloatProperty()
+   arg_int: bpy.props.IntProperty()
+   arg_tipo: bpy.props.EnumProperty( name='Type',
+                                     items=[(str(0x00),'NUL',''),
+                                            (str(0x01),'INT',''),
+                                            (str(0x02),'FLT',''),
+                                            (str(0x04),'ENT',''),
+                                            (str(0x08),'STR',''),
+                                            (str(0x10),'VAR','')])
+#}
+
+class SR_UL_ENT_EVENT_LIST(bpy.types.UIList):
+#{
+   bl_idname = 'SR_UL_ENT_EVENT_LIST'
+   def draw_item(_,context,layout,data,item,icon,active_data,active_propname):
+   #{
+      clicker = layout.column()
+      clicker.label( text='', icon='DECORATE_DRIVER' )
+      clicker.ui_units_x = 1
+
+      src_ev = layout.column()
+      src_ev.prop( item, 'source_event', text='',emboss=True )
+      src_ev.label( text='...' )
+
+      dely = layout.column()
+      if item.delay < 0.0:
+         dely.alert=True
+      dely.ui_units_x = 4
+      dely.prop( item, 'delay', text='After' )
+
+      jf = layout.column()
+      jf.label( text='', icon='FORWARD' )
+      jf.ui_units_x = 1
+
+      rec = layout.column()
+      if item.reciever == None:
+         rec.alert=True
+      rec.prop( item, 'reciever', text='',emboss=True )
+      rec.label( text=(item.reciever.SR_data.ent_type if item.reciever else '') + \
+                      (' (self)' if item.reciever == context.active_object else '' ) )
+
+      rec_ev = layout.column()
+      errstr = None
+      if item.reciever:
+      #{
+         tipo = item.reciever.SR_data.ent_type
+         cls = globals()[ tipo ]
+         table = getattr( cls, 'sr_functions', None )
+         if table:
+         #{
+            if item.reciever_event not in table:
+            #{
+               rec_ev.alert=True
+               errstr = 'BAD FUNCTION ID'
+            #}
+         #}
+      #}
+
+      rec_ev.prop( item, 'reciever_event', text='',emboss=True )
+      if errstr:
+         rec_ev.label( text=errstr, icon='ERROR' )
+
+      tt = layout.column()
+      tt.prop( item, 'arg_tipo',text='',emboss=True )
+      tipo = int(item.arg_tipo)
+      if   tipo == 0x00: tt.label( text='CALL' )
+      elif tipo == 0x01: tt.prop( item, 'arg_int', text='' )
+      elif tipo == 0x02: tt.prop( item, 'arg_float', text='' )
+      elif tipo == 0x04: tt.prop( item, 'arg_entity', text='' )
+      elif tipo == 0x08: tt.prop( item, 'arg_string', text='' )
+   #}
 #}
 
 class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
@@ -2115,8 +2363,7 @@ class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
    ent_font: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_FONT)
    ent_traffic: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_TRAFFIC)
    ent_skateshop: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_SKATESHOP)
-   ent_swspreview: \
-         bpy.props.CollectionProperty(type=SR_OBJECT_ENT_WORKSHOP_PREVIEW)
+   ent_swspreview: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_WORKSHOP_PREVIEW)
    ent_worldinfo: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_WORLD_INFO)
    ent_ccmd: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_CCMD)
    ent_objective: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_OBJECTIVE)
@@ -2128,12 +2375,16 @@ class SR_OBJECT_PROPERTIES(bpy.types.PropertyGroup):
    ent_glider: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_GLIDER)
    ent_npc: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_NPC)
    ent_script: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_SCRIPT)
+   ent_logic: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_LOGIC)
 
    ent_type: bpy.props.EnumProperty(
       name="Type",
       items=sr_entity_list,
       update=sr_on_type_change
    )
+
+   events: bpy.props.CollectionProperty(type=SR_OBJECT_ENT_EVENT_ENTRY)
+   events_index: bpy.props.IntProperty()
 #}
 
 class SR_MESH_PROPERTIES(bpy.types.PropertyGroup):
@@ -2222,6 +2473,12 @@ class SR_MATERIAL_PROPERTIES(bpy.types.PropertyGroup):
       ('6','sand (medium friction)','')
       ])
    
+   additive: bpy.props.BoolProperty( \
+         name="Additive rendering",\
+         default=False,\
+         description = "Draw without writing to depth in additive blending mode"\
+   )
+   
    collision: bpy.props.BoolProperty( \
          name="Collisions Enabled",\
          default=True,\
@@ -2314,6 +2571,22 @@ class SR_MATERIAL_PROPERTIES(bpy.types.PropertyGroup):
    tex_diffuse_rt: bpy.props.IntProperty( name="diffuse: RT index", default=-1 )
 #}
 
+class SR_MARKER_PROPERTIES(bpy.types.PropertyGroup):
+#{
+   tipo: bpy.props.EnumProperty(items=(('0', 'Camera', ""),
+                                       ('1', 'Event', ""),
+                                       ('2', 'Subtitle', ""),
+                                       ('3', 'Fadeout', "") ))
+   event_string: bpy.props.StringProperty( name="Event String" )
+   subtitle_person: bpy.props.EnumProperty( items=(('0','Default',""),
+                                                   ('1','JC',""),
+                                                   ('2','Mike',""),
+                                                   ('3','FBI',""),
+                                                   ('4','Human Reserved',""),
+                                                   ('5','Gino',"")) )
+   subtitle_en: bpy.props.StringProperty( name="EN" )
+#}
+
 # ---------------------------------------------------------------------------- #
 #                                                                              #
 #                                 GUI section                                  #
@@ -2324,8 +2597,7 @@ cv_view_draw_handler = None
 cv_view_pixel_handler = None
 
 cv_legacy = bpy.app.version < (4,0,0)
-cv_view_shader = gpu.shader.from_builtin( '3D_SMOOTH_COLOR' if cv_legacy else \
-                                          'SMOOTH_COLOR')
+cv_view_shader = gpu.shader.from_builtin( '3D_SMOOTH_COLOR' if cv_legacy else 'SMOOTH_COLOR')
 cv_view_verts = []
 cv_view_colours = []
 cv_view_course_i = 0
@@ -2850,11 +3122,6 @@ def cv_ent_volume( obj ):
       cc = (0,0,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) )
-   #}
 #}
 
 def cv_draw_route( route, dij ):
@@ -2865,8 +3132,7 @@ def cv_draw_route( route, dij ):
          route.SR_data.ent_route[0].colour[1],
          route.SR_data.ent_route[0].colour[2])
 
-   cv_draw_ucube(route.matrix_world,cc,Vector((0.5,-7.5,6)),\
-                                       Vector((0,-6.5,5.5)))
+   cv_draw_ucube(route.matrix_world,cc,Vector((0.5,-7.5,6)),Vector((0,-6.5,5.5)))
    cv_draw_ucube(route.matrix_world,cc,pole, Vector(( 0.5, 0.5,0)) )
    cv_draw_ucube(route.matrix_world,cc,pole, Vector(( 0.5,-13.5,0)) )
    cv_draw_ucube(route.matrix_world,cc,hat, Vector((-0.5,-6.5, 12)) )
@@ -2874,7 +3140,8 @@ def cv_draw_route( route, dij ):
 
    checkpoints = route.SR_data.ent_route[0].gates
 
-   for i in range(len(checkpoints)):#{
+   for i in range(len(checkpoints)):
+   #{
       gi = checkpoints[i].target
       gj = checkpoints[(i+1)%len(checkpoints)].target
 
@@ -2894,7 +3161,8 @@ def cv_draw_route( route, dij ):
 
       path = solve_graph( dij, gi.name, gj.name )
 
-      if path:#{
+      if path:
+      #{
          cv_draw_arrow(gi.location,dij.points[path[0]],cc,1.5,False)
          cv_draw_arrow(dij.points[path[len(path)-1]],gj.location,cc,1.5,False)
          for j in range(len(path)-1):#{
@@ -2932,46 +3200,58 @@ def cv_draw():#{
    route_curves = []
    routes = []
 
-   for obj in bpy.context.collection.objects:#{
-      if obj.type == 'ARMATURE':#{
+   for obj in bpy.context.collection.objects:
+   #{
+      if obj.type == 'ARMATURE':
+      #{
          if obj.data.pose_position == 'REST':
             draw_skeleton_helpers( obj )
       #}
-      else:#{
+      else:
+      #{
+         for evi,ev in enumerate(obj.SR_data.events):
+         #{
+            c = (0.2,0.2,0.2)
+
+            if (obj == bpy.context.active_object) and (obj.SR_data.events_index == evi):
+               c = (0.3,0.7,1)
+
+            if ev.reciever:
+            #{
+               cv_draw_arrow( obj.location, ev.reciever.location, c )
+
+               if int(ev.arg_tipo) == 0x04:
+               #{
+                  if ev.arg_entity:
+                  #{
+                     p0 = (obj.location+ev.reciever.location)*Vector((0.5,0.5,0.5))
+                     cv_draw_line_dotted( p0, ev.arg_entity.location, c )
+                  #}
+               #}
+            #}
+         #}
+
          ent_type = obj_ent_type( obj )
 
-         if ent_type == 'ent_gate':#{
+         if ent_type == 'ent_gate':
+         #{
             cv_ent_gate( obj )
             route_gates += [obj]
          #}
-         elif ent_type == 'ent_route_node':#{
-            if obj.type == 'CURVE':#{
+         elif ent_type == 'ent_route_node':
+         #{
+            if obj.type == 'CURVE':
                route_curves += [obj]
-            #}
          #}
          elif ent_type == 'ent_route':
             routes += [obj]
-         elif ent_type == 'ent_volume':#{
+         elif ent_type == 'ent_volume':
             cv_ent_volume( obj )
-         #}
-         elif ent_type == 'ent_objective':#{
+         elif ent_type == 'ent_objective':
+         #{
             data = obj.SR_data.ent_objective[0]
-            if data.proxima:#{
+            if data.proxima:
                cv_draw_arrow( obj.location, data.proxima.location, (1,0.6,0.2) )
-            #}
-            if data.target:
-               cv_draw_arrow( obj.location, data.target.location, (0,1,0) )
-         #}
-         elif ent_type == 'ent_relay':#{
-            data = obj.SR_data.ent_relay[0]
-            if data.target0:
-               cv_draw_arrow( obj.location, data.target0.location, (1,1,1) )
-            if data.target1:
-               cv_draw_arrow( obj.location, data.target1.location, (1,1,1) )
-            if data.target2:
-               cv_draw_arrow( obj.location, data.target2.location, (1,1,1) )
-            if data.target3:
-               cv_draw_arrow( obj.location, data.target3.location, (1,1,1) )
          #}
          elif ent_type == 'ent_list':
          #{
@@ -2985,27 +3265,8 @@ def cv_draw():#{
                #}
             #}
          #}
-         elif ent_type == 'ent_script':
-         #{
-            data = obj.SR_data.ent_script[0]
-            
-            cc = (0.9,0.0,0.7)
-
-            cv_draw_ucube( obj.matrix_world, cc, Vector((0.1,0.1,0.1)) )
-            cv_draw_ucube( obj.matrix_world, cc, Vector((0.2,0.2,0.2)) )
-
-            if data.entity_list:
-            #{
-               cv_draw_arrow( obj.location, data.entity_list.location, cc )
-               cv_draw_arrow( data.entity_list.location, obj.location, cc )
-            #}
-         #}
          elif ent_type == 'ent_challenge':#{
             data = obj.SR_data.ent_challenge[0]
-            if data.target:
-               cv_draw_arrow( obj.location, data.target.location, (0,0.4,0.8) )
-            if data.complete:
-               cv_draw_arrow( obj.location, data.complete.location, (0.1,0.9,0) )
             if data.first:
                cv_draw_arrow( obj.location, data.first.location, (1,0.6,0.2) )
             if data.reset_spawn:
@@ -3139,13 +3400,6 @@ def cv_draw():#{
             if display1:
                cv_draw_ucube(display1.matrix_world, cc1, display_cu, display_co)
          #}
-         elif ent_type == 'ent_region':
-         #{
-            data = obj.SR_data.ent_region[0]
-            if data.target0:#{
-               cv_draw_arrow( obj.location, data.target0.location, (.5,.5,.5), 0.1 )
-            #}
-         #}
       #}
    #}
 
@@ -3165,29 +3419,62 @@ def pos3d_to_2d( pos ):#{
             bpy.context.space_data.region_3d, pos )
 #}
 
-def cv_draw_pixel():#{
-   if not bpy.context.scene.SR_data.gizmos: return
+def cv_draw_pixel():
+#{
+   if not bpy.context.scene.SR_data.gizmos: 
+      return
    blf.size(0,10)
    blf.color(0, 1.0,1.0,1.0,0.9)
    blf.enable(0,blf.SHADOW)
-   blf.shadow(0,3,0.0,0.0,0.0,1.0)
-   for obj in bpy.context.collection.objects:#{
+   blf.shadow(0,6,0.0,0.0,0.0,1.0)
+   for obj in bpy.context.collection.objects:
+   #{
       ent_type = obj_ent_type( obj )
-      
-      if ent_type != 'none':#{
+      if ent_type != 'none':
+      #{
          co = pos3d_to_2d( obj.location )
 
-         if not co: continue
+         if not co: 
+            continue
+
          blf.position(0,co[0],co[1],0)
          blf.draw(0,ent_type)
+
+         if ent_type == 'ent_logic':
+         #{
+            data = obj.SR_data.ent_logic[0]
+            blf.color(0,0.6,0.9,0.3,1.0)
+            blf.position(0,co[0],co[1]-16,0)
+
+            tipo = int(data.tipo)
+            if tipo == 0x10:
+               blf.draw(0, F'AND' )
+            elif tipo == 0x20:
+               blf.draw(0, F'NOT' )
+            elif tipo == 0x40:
+               blf.draw(0, F'OR')
+            elif tipo == 0x100:
+               blf.draw(0, F"atom('{data.atom_alias}') == '{data.atom_enum_value}'" )
+            blf.color(0,1.0,1.0,1.0,1.0)
+         #}
+         if ent_type == 'ent_script':
+         #{
+            data = obj.SR_data.ent_script[0]
+            blf.color(0,0.6,0.9,0.3,1.0)
+            blf.position(0,co[0],co[1]-16,0)
+            blf.draw(0, F"'{data.script_alias}'" )
+            blf.color(0,1.0,1.0,1.0,1.0)
+         #}
       #}
    #}
 #}
 
-classes = [ SR_INTERFACE, SR_MATERIAL_PANEL,\
+classes = [ SR_INTERFACE, SR_MATERIAL_PANEL, SR_MARKER_PANEL, SR_ENTITY_PANEL, \
             SR_COLLECTION_SETTINGS, SR_SCENE_SETTINGS, \
             SR_COMPILE, SR_COMPILE_THIS,SR_COMPILE_METASCENE, SR_MIRROR_BONE_X,\
             \
+            SR_OT_ENT_EVENT_NEW_ITEM, SR_OT_ENT_EVENT_DEL_ITEM, \
+            SR_OBJECT_ENT_EVENT_ENTRY, SR_UL_ENT_EVENT_LIST, \
             SR_OBJECT_ENT_GATE, SR_MESH_ENT_GATE, SR_OBJECT_ENT_SPAWN, \
             SR_OBJECT_ENT_ROUTE_ENTRY, SR_UL_ROUTE_NODE_LIST, \
             SR_OBJECT_ENT_ROUTE, SR_OT_ROUTE_LIST_NEW_ITEM,\
@@ -3211,10 +3498,10 @@ classes = [ SR_INTERFACE, SR_MATERIAL_PANEL,\
             SR_OBJECT_ENT_RELAY,SR_OBJECT_ENT_MINIWORLD,\
             SR_OBJECT_ENT_LIST_ENTRY, SR_UL_ENT_LIST, SR_OBJECT_ENT_LIST, \
             SR_OT_ENT_LIST_NEW_ITEM, SR_OT_ENT_LIST_DEL_ITEM,\
-            SR_OBJECT_ENT_GLIDER, SR_OBJECT_ENT_NPC, SR_OBJECT_ENT_SCRIPT, \
+            SR_OBJECT_ENT_GLIDER, SR_OBJECT_ENT_NPC, SR_OBJECT_ENT_SCRIPT, SR_OBJECT_ENT_LOGIC, \
             \
             SR_OBJECT_PROPERTIES, SR_LIGHT_PROPERTIES, SR_BONE_PROPERTIES, 
-            SR_MESH_PROPERTIES, SR_MATERIAL_PROPERTIES \
+            SR_MESH_PROPERTIES, SR_MATERIAL_PROPERTIES, SR_MARKER_PROPERTIES \
            ]
 
 def register():
@@ -3222,27 +3509,18 @@ def register():
    for c in classes:
       bpy.utils.register_class(c)
 
-   bpy.types.Scene.SR_data = \
-         bpy.props.PointerProperty(type=SR_SCENE_SETTINGS)
-   bpy.types.Collection.SR_data = \
-         bpy.props.PointerProperty(type=SR_COLLECTION_SETTINGS)
-
-   bpy.types.Object.SR_data = \
-         bpy.props.PointerProperty(type=SR_OBJECT_PROPERTIES)
-   bpy.types.Light.SR_data = \
-         bpy.props.PointerProperty(type=SR_LIGHT_PROPERTIES)
-   bpy.types.Bone.SR_data = \
-         bpy.props.PointerProperty(type=SR_BONE_PROPERTIES)
-   bpy.types.Mesh.SR_data = \
-         bpy.props.PointerProperty(type=SR_MESH_PROPERTIES)
-   bpy.types.Material.SR_data = \
-         bpy.props.PointerProperty(type=SR_MATERIAL_PROPERTIES)
+   bpy.types.Scene.SR_data = bpy.props.PointerProperty(type=SR_SCENE_SETTINGS)
+   bpy.types.Collection.SR_data = bpy.props.PointerProperty(type=SR_COLLECTION_SETTINGS)
+   bpy.types.Object.SR_data = bpy.props.PointerProperty(type=SR_OBJECT_PROPERTIES)
+   bpy.types.Light.SR_data = bpy.props.PointerProperty(type=SR_LIGHT_PROPERTIES)
+   bpy.types.Bone.SR_data = bpy.props.PointerProperty(type=SR_BONE_PROPERTIES)
+   bpy.types.Mesh.SR_data = bpy.props.PointerProperty(type=SR_MESH_PROPERTIES)
+   bpy.types.Material.SR_data = bpy.props.PointerProperty(type=SR_MATERIAL_PROPERTIES)
+   bpy.types.TimelineMarker.SR_data = bpy.props.PointerProperty(type=SR_MARKER_PROPERTIES)
 
    global cv_view_draw_handler, cv_view_pixel_handler
-   cv_view_draw_handler = bpy.types.SpaceView3D.draw_handler_add(\
-      cv_draw,(),'WINDOW','POST_VIEW')
-   cv_view_pixel_handler = bpy.types.SpaceView3D.draw_handler_add(\
-      cv_draw_pixel,(),'WINDOW','POST_PIXEL')
+   cv_view_draw_handler = bpy.types.SpaceView3D.draw_handler_add( cv_draw,(),'WINDOW','POST_VIEW')
+   cv_view_pixel_handler = bpy.types.SpaceView3D.draw_handler_add( cv_draw_pixel,(),'WINDOW','POST_PIXEL')
 #}
 
 def unregister():
index 35396666570f7a38fcbb22c19ac59ebbcc19608f..5f5a60f0a7453550ee932b95eb208ae5296bd20b 100644 (file)
@@ -197,7 +197,14 @@ def sr_compile_material( mat ):
       #}
    #}
 
-   if mat.SR_data.shader == 'standard': m.shader = 0
+   if mat.SR_data.shader == 'standard': 
+   #{
+      m.shader = 0
+      flags = 0
+      if mat.SR_data.additive:
+         flags |= 0x20
+      shader_prop_u32( msg, 'render_flags', flags )
+   #}
    if mat.SR_data.shader == 'standard_cutout': m.shader = 1
    if mat.SR_data.shader == 'foliage': m.shader = 10
    if mat.SR_data.shader == 'terrain_blend':
index f7383f2fe8fb83f0fc9a377ce5723a7c72f8d63f..75db2213d8d00ea618bf64c1c720ab886d8d9bf9 100644 (file)
@@ -570,7 +570,8 @@ def _mdl_compiler_compile_entities():
             light.colour[3] = obj.data.energy
             sr_ent_push( light )
          #}
-         elif ent_type == 'ent_camera': #{
+         elif ent_type == 'ent_camera': 
+         #{
             cam = ent_camera()
 
             trans = mdl_transform()
@@ -616,15 +617,18 @@ def _mdl_compiler_compile_entities():
             cam.fov = obj.data.angle_y * 57.2958
             sr_ent_push(cam)
          #}
-         elif ent_type == 'ent_gate': #{
+         elif ent_type == 'ent_gate':
+         #{
             gate = ent_gate()
             obj_data = obj.SR_data.ent_gate[0]
             mesh_data = obj.data.SR_data.ent_gate[0]
 
             flags = 0x0000
 
-            if obj_data.tipo == 'default':#{
-               if obj_data.target:#{
+            if obj_data.tipo == 'default':
+            #{
+               if obj_data.target:
+               #{
                   gate.target = _mdl_compiler.entity_ids[obj_data.target.name]
                   flags |= 0x0001
                #}
@@ -637,15 +641,14 @@ def _mdl_compiler_compile_entities():
                flags |= 0x0002
             #}
             elif obj_data.tipo == 'passive':
-            #{
                flags |= 0x80
-            #}
 
-            if obj_data.flip:   flags |= 0x0004
-            if obj_data.custom:#{
+            if obj_data.flip:
+               flags |= 0x0004
+            if obj_data.custom:
+            #{
                flags |= 0x0008
-               gate.submesh_start, gate.submesh_count, _ = \
-                     mdl_compile_mesh_internal( obj )
+               gate.submesh_start, gate.submesh_count, _ = mdl_compile_mesh_internal( obj )
             #}
             if obj_data.locked: flags |= 0x0010
             if obj_data.no_linkback: flags |= 0x0040
@@ -658,14 +661,15 @@ def _mdl_compiler_compile_entities():
             q  = [obj.matrix_local.to_quaternion(), (0,0,0,1)]
             co = [obj.matrix_world @ Vector((0,0,0)), (0,0,0)]
 
-            if obj_data.target:#{
+            if obj_data.target:
+            #{
                q[1] = obj_data.target.matrix_local.to_quaternion()
                co[1]= obj_data.target.matrix_world @ Vector((0,0,0))
             #}
             
             # Setup transform
-            #
-            for x in range(2):#{
+            for x in range(2):
+            #{
                gate.co[x][0] =  co[x][0]
                gate.co[x][1] =  co[x][2]
                gate.co[x][2] = -co[x][1]
@@ -677,7 +681,8 @@ def _mdl_compiler_compile_entities():
 
             sr_ent_push( gate )
          #}
-         elif ent_type == 'ent_spawn': #{
+         elif ent_type == 'ent_spawn': 
+         #{
             spawn = ent_spawn()
             compile_obj_transform( obj, spawn.transform )
             obj_data = obj.SR_data.ent_spawn[0]
@@ -685,13 +690,15 @@ def _mdl_compiler_compile_entities():
             spawn.flags = obj_data.flags
             sr_ent_push( spawn )
          #}
-         elif ent_type == 'ent_water':#{
+         elif ent_type == 'ent_water':
+         #{
             water = ent_water()
             compile_obj_transform( obj, water.transform )
             water.max_dist = 0.0
             sr_ent_push( water )
          #}
-         elif ent_type == 'ent_audio':#{
+         elif ent_type == 'ent_audio':
+         #{
             obj_data = obj.SR_data.ent_audio[0]
             audio = ent_audio()
             compile_obj_transform( obj, audio.transform )
@@ -759,22 +766,11 @@ def _mdl_compiler_compile_entities():
             #   volume.flags |= 0x4
             compile_obj_transform( obj, volume.transform )
 
-            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
-            #}
 
             sr_ent_push(volume)
          #}
@@ -823,7 +819,8 @@ def _mdl_compiler_compile_entities():
             workshop_preview.id_camera = sr_entity_id( obj_data.cam )
             sr_ent_push( workshop_preview )
          #}
-         elif ent_type == 'ent_worldinfo':#{
+         elif ent_type == 'ent_worldinfo':
+         #{
             worldinfo = ent_worldinfo()
             obj_data = obj.SR_data.ent_worldinfo[0]
             worldinfo.pstr_name = _af_pack_string( obj_data.name )
@@ -853,26 +850,18 @@ def _mdl_compiler_compile_entities():
             worldinfo.wind_scale = obj_data.wind_scale
             sr_ent_push( worldinfo )
          #}
-         elif ent_type == 'ent_ccmd':#{
+         elif ent_type == 'ent_ccmd':
+         #{
             ccmd = ent_ccmd()
             obj_data = obj.SR_data.ent_ccmd[0]
             ccmd.pstr_command = _af_pack_string( obj_data.command )
             sr_ent_push( ccmd )
          #}
-         elif ent_type == 'ent_script':#{
-            obj_data = obj.SR_data.ent_script[0]
-            script = ent_script()
-            script.pstr_script_name = _af_pack_string( obj_data.script_alias )
-            script.entity_list_id = sr_entity_id( obj_data.entity_list )
-            script.falgs = obj_data.flags
-            sr_ent_push( script )
-         #}
-         elif ent_type == 'ent_objective':#{
+         elif ent_type == 'ent_objective':
+         #{
             objective = ent_objective()
             obj_data = obj.SR_data.ent_objective[0]
             objective.id_next = sr_entity_id( obj_data.proxima )
-            # objective.id_win = sr_entity_id( obj_data.target )
-            # objective.win_event = obj_data.target_event
             objective.filter = int(obj_data.filtrar)
             objective.filter2 = 0
             objective.time_limit = obj_data.time_limit
@@ -881,9 +870,7 @@ def _mdl_compiler_compile_entities():
             objective.submesh_start, objective.submesh_count, _ = mdl_compile_mesh_internal( obj )
 
             if obj_data.description != '':
-            #{
                objective.pstr_description_ui = _af_pack_string( obj_data.description )
-            #}
 
             sr_ent_push( objective )
          #}
@@ -896,10 +883,7 @@ def _mdl_compiler_compile_entities():
             challenge.flags = 0x00
             if obj_data.time_limit: challenge.flags |= 0x01
             if obj_data.is_story: challenge.flags |= 0x02
-            challenge.on_activate_id = sr_entity_id( obj_data.target )
-            challenge.on_activate_event = obj_data.target_event
-            challenge.on_complete_id = sr_entity_id( obj_data.complete )
-            challenge.on_complete_event = obj_data.complete_event
+            if obj_data.any_order: challenge.flags |= 0x08
             challenge.first_objective_id = sr_entity_id( obj_data.first )
             challenge.camera_id = sr_entity_id( obj_data.camera )
             challenge.status = 0
@@ -923,37 +907,24 @@ def _mdl_compiler_compile_entities():
                #{
                   list_entry = file_entity_ref()
                   list_entry.entity_id = sr_entity_id( obj_data.entities[k].target )
+                  if obj_data.entities[k].alias:
+                     list_entry.pstr_alias = _af_pack_string( obj_data.entities[k].alias )
                   sr_ent_push( list_entry )
                   lista.entity_ref_count += 1
                #}
             #}
             sr_ent_push( lista )
          #}
-         elif ent_type == 'ent_region':#{
+         elif ent_type == 'ent_region':
+         #{
             region = ent_region()
             obj_data = obj.SR_data.ent_region[0]
             compile_obj_transform( obj, region.transform )
-            region.submesh_start, region.submesh_count, _ = \
-                  mdl_compile_mesh_internal( obj )
+            region.submesh_start, region.submesh_count, _ = mdl_compile_mesh_internal( obj )
             region.pstr_title = _af_pack_string( obj_data.title )
             region.list_id = sr_entity_id( obj_data.zone_volume )
-            region.target0[0] = sr_entity_id( obj_data.target0 )
-            region.target0[1] = obj_data.target0_event
             sr_ent_push( region )
          #}
-         elif ent_type == 'ent_relay':#{
-            relay = ent_relay()
-            obj_data = obj.SR_data.ent_relay[0]
-            relay.targets[0][0] = sr_entity_id( obj_data.target0 )
-            relay.targets[1][0] = sr_entity_id( obj_data.target1 )
-            relay.targets[2][0] = sr_entity_id( obj_data.target2 )
-            relay.targets[3][0] = sr_entity_id( obj_data.target3 )
-            relay.targets[0][1] = obj_data.target0_event
-            relay.targets[1][1] = obj_data.target1_event
-            relay.targets[2][1] = obj_data.target2_event
-            relay.targets[3][1] = obj_data.target3_event
-            sr_ent_push( relay )
-         #}
          elif ent_type == 'ent_glider':
          #{
             glider = ent_glider()
@@ -969,6 +940,14 @@ def _mdl_compiler_compile_entities():
             npc.pstr_context_id =  _af_pack_string( obj_data.context_id )
             sr_ent_push( npc )
          #}
+         elif ent_type == 'ent_script':#{
+            obj_data = obj.SR_data.ent_script[0]
+            script = ent_script()
+            script.pstr_script_name = _af_pack_string( obj_data.script_alias )
+            #script.entity_list_id = sr_entity_id( obj_data.entity_list )
+            script.falgs = obj_data.flags
+            sr_ent_push( script )
+         #}
          elif ent_type == 'ent_cubemap':
          #{
             cubemap = ent_cubemap()
@@ -980,24 +959,12 @@ def _mdl_compiler_compile_entities():
             cubemap.live = 60
             sr_ent_push( cubemap )
          #}
-         elif ent_type == 'ent_miniworld':
-         #{
-            miniworld = ent_miniworld()
-            obj_data = obj.SR_data.ent_miniworld[0]
-
-            compile_obj_transform( obj, miniworld.transform )
-            miniworld.pstr_world = _af_pack_string( obj_data.world )
-            miniworld.proxy = sr_entity_id( obj_data.proxy )
-            miniworld.camera = sr_entity_id( obj_data.camera )
-            sr_ent_push( miniworld )
-         #}
          elif ent_type == 'ent_prop':
          #{
             prop = ent_prop()
             obj_data = obj.SR_data.ent_prop[0]
             compile_obj_transform( obj, prop.transform )
-            prop.submesh_start, prop.submesh_count, _ = \
-                  mdl_compile_mesh_internal( obj )
+            prop.submesh_start, prop.submesh_count, _ = mdl_compile_mesh_internal( obj )
             prop.flags = obj_data.flags
             prop.pstr_alias = _af_pack_string( obj_data.alias )
             sr_ent_push( prop )
@@ -1117,6 +1084,23 @@ def _mdl_compiler_compile_entities():
 
             sr_ent_push(traffic)
          #}
+
+         for evi,ev in enumerate(obj.SR_data.events):
+         #{
+            event = ent_event()
+            event.pstr_source_event = _af_pack_string( ev.source_event )
+            event.pstr_recieve_event = _af_pack_string( ev.reciever_event )
+            event.source_entity_id = sr_entity_id( obj )
+            event.recieve_entity_id = sr_entity_id( ev.reciever )
+            event.delay = ev.delay
+            event.flags = int(ev.arg_tipo)
+            if event.flags == 0x01: event.data.const_i32 = ev.arg_int
+            if event.flags == 0x02: event.data.const_f32 = ev.arg_float
+            if event.flags == 0x04: event.data.const_entity_id = sr_entity_id( ev.arg_entity )
+            if event.flags == 0x08: event.data.const_pstr = _af_pack_string( ev.arg_string )
+            if event.flags == 0x10: event.data.pstr_data_alias = 0
+            sr_ent_push(event)
+         #}
       #}
    #}
 
index 5e31baa716fbce8512a1252b8259b44ba4146da6..b28fc62045c2f900a481c16a34b30cacd776165c 100644 (file)
@@ -63,21 +63,50 @@ class ms_track(Structure):
                ("semantic_type",c_uint32)]   # runtime
 #}
 
-class ms_strip(Structure):
+class ms_strip_data(Structure):
 #{
-   _fields_ = [("data_start",c_uint32), # keyframes in block mode, or tracks in
-                                        # curves mode.
-               ("data_count",c_uint32), # tracks in curves, bone count in kfs
-               ("data_mode",c_uint32),
-               ("offset",c_uint32),
+   _fields_ = [("start",c_uint32),
+               ("count",c_uint32),
                ("length",c_uint32),
-               ("pstr_name",c_uint32),          #AKA Blender NLAStrip name
-               ("pstr_internal_name",c_uint32), #AKA Blender action name
-               ("instance_id",c_uint32),# 0 ... 0xfffffffe, or 0xffffffff
-               ("object_id",c_uint32),  # First class: SR entity ID,
-                                        # Second class: instance override index
+               ("pstr_name",c_uint32),
+               ("pstr_internal_name",c_uint32),
+               ("instance_id",c_uint32),
+               ("object_id",c_uint32),
+               ("timing_offset",c_float)]
+#}
+
+class ms_strip_data_camera(Structure):
+#{
+   _fields_ = [("entity_id",c_uint32)]
+#}
+
+class ms_strip_data_subtitle(Structure):
+#{
+   _fields_ = [("pstr_en",c_uint32),
+               ("res0",c_uint32),
+               ("res1",c_uint32),
+               ("res2",c_uint32),
+               ("character",c_uint8)]
+#}
 
-               ("timing_offset",c_float),]
+class ms_strip_data_event(Structure):
+#{
+   _fields_ = [("pstr_string",c_uint32)]
+#}
+
+class ms_strip_data_union(Union):
+#{
+   _fields_ = [("strip",ms_strip_data),
+               ("camera",ms_strip_data_camera),
+               ("subtitle",ms_strip_data_subtitle),
+               ("event",ms_strip_data_event)]
+#}
+
+class ms_strip(Structure):
+#{
+   _fields_ = [("mode",c_uint8),
+               ("offset",c_uint32),
+               ("anon",ms_strip_data_union)]
 #}
 
 class ms_instance(Structure):
@@ -93,21 +122,6 @@ class ms_override(Structure):
                ("transform",mdl_transform)]
 #}
 
-def _metascene_action_cache( out_strip, action ):
-#{
-   if action.name in _ms_compiler.action_cache:
-   #{
-      print( "      Using cached action data" )
-      ref = _ms_compiler.action_cache[ action.name ]
-      out_strip.data_start = ref.data_start
-      out_strip.data_count = ref.data_count
-      out_strip.data_mode = ref.data_mode
-      out_strip.pstr_internal_name = ref.pstr_internal_name
-      return True
-   #}
-   else: return False
-#}
-
 def _sr_metascene_dryrun():
 #{
    scene = bpy.context.scene
@@ -179,11 +193,11 @@ def _metascene_comp_armature_range( obj, start, end, out_strip ):
 #{
    bones = [_ for _ in sr_armature_bones( obj )]
    out_strip.offset = math.floor( start )
-   out_strip.length = math.ceil( end - out_strip.offset )
-   out_strip.timing_offset = 0.0
-   out_strip.data_mode = 0
-   out_strip.data_start = len( _ms_compiler.keyframes )
-   out_strip.data_count = len( bones )
+   out_strip.anon.strip.length = math.ceil( end - out_strip.offset )
+   out_strip.anon.strip.timing_offset = 0.0
+   out_strip.anon.strip.mode = 0x1
+   out_strip.anon.strip.start = len( _ms_compiler.keyframes )
+   out_strip.anon.strip.count = len( bones )
 
    unfuck = Matrix([(1,0,0,0),(0,0,1,0),(0,-1,0,0),(0,0,0,1)])
 
@@ -242,9 +256,9 @@ def _metascene_comp_armature_range( obj, start, end, out_strip ):
          kf.q[1]  =  rq[3]
          kf.q[2]  = -rq[2]
          kf.q[3]  =  rq[0]
-         kf.s[0]  = 1.0 #sca[0]
-         kf.s[1]  = 1.0 #sca[1]
-         kf.s[2]  = 1.0 #sca[2]
+         kf.s[0]  = sca[0]
+         kf.s[1]  = sca[2]
+         kf.s[2]  = sca[1]
          
          _ms_compiler.keyframes.append(kf)
       #}
@@ -289,10 +303,11 @@ def _metascene_armature_anims( obj, instance_id, override_id ):
             obj.animation_data.action = action
 
             out_strip = ms_strip()
-            out_strip.pstr_name = _af_pack_string( NLAStrip.name )
-            out_strip.pstr_internal_name = _af_pack_string( action.name )
-            out_strip.instance_id = instance_id
-            out_strip.object_id = override_id
+            out_strip.mode = 0x1
+            out_strip.anon.strip.pstr_name = _af_pack_string( NLAStrip.name )
+            out_strip.anon.strip.pstr_internal_name = _af_pack_string( action.name )
+            out_strip.anon.strip.instance_id = instance_id
+            out_strip.anon.strip.object_id = override_id
 
             _metascene_comp_armature_range( obj, int(NLAStrip.frame_start), int(NLAStrip.frame_end), out_strip )
 
@@ -348,10 +363,11 @@ def _metascene_armature_anims( obj, instance_id, override_id ):
                internal_name = F"{obj.name}.{strip_count}"
 
                out_strip = ms_strip()
-               out_strip.pstr_name = _af_pack_string( F"{obj.name}(amalg)" )
-               out_strip.pstr_internal_name = _af_pack_string( internal_name )
-               out_strip.instance_id = instance_id
-               out_strip.object_id = override_id
+               out_strip.mode = 0x1
+               out_strip.anon.strip.pstr_name = _af_pack_string( F"{obj.name}(amalg)" )
+               out_strip.anon.strip.pstr_internal_name = _af_pack_string( internal_name )
+               out_strip.anon.strip.instance_id = instance_id
+               out_strip.anon.strip.object_id = override_id
 
                _metascene_comp_armature_range( obj, frame_start, frame, out_strip )
                _ms_compiler.strips.append( out_strip )
@@ -372,12 +388,11 @@ def _metascene_armature_anims( obj, instance_id, override_id ):
 
 def _metascene_compile_action_curves( out_strip, action ):
 #{
-   if _metascene_action_cache( out_strip, action ): return
-
-   out_strip.data_mode = 1
-   out_strip.data_start = len(_ms_compiler.tracks)
-   out_strip.data_count = len(action.fcurves)
-   out_strip.pstr_internal_name = _af_pack_string( action.name )
+   #if _metascene_action_cache( out_strip, action ): return
+   out_strip.mode = 0x2
+   out_strip.anon.strip.start = len(_ms_compiler.tracks)
+   out_strip.anon.strip.count = len(action.fcurves)
+   out_strip.anon.strip.pstr_internal_name = _af_pack_string( action.name )
 
    for fcurve in action.fcurves:
    #{
@@ -445,13 +460,12 @@ def _metascene_camera_anims( obj, entity_id ):
 
             out_strip = ms_strip()
             _metascene_compile_action_curves( out_strip, NLAStrip.action )
-            out_strip.instance_id = 0xffffffff
-            out_strip.object_id = entity_id
-            out_strip.offset = math.floor( NLAStrip.frame_start )
-            out_strip.timing_offset = NLAStrip.action_frame_start
-            out_strip.length = math.ceil( NLAStrip.frame_end - out_strip.offset )
-            out_strip.pstr_name = _af_pack_string( NLAStrip.name )
-
+            out_strip.anon.strip.instance_id = 0xffffffff
+            out_strip.anon.strip.object_id = entity_id
+            out_strip.anon.strip.offset = math.floor( NLAStrip.frame_start )
+            out_strip.anon.strip.timing_offset = NLAStrip.action_frame_start
+            out_strip.anon.strip.length = math.ceil( NLAStrip.frame_end - out_strip.offset )
+            out_strip.anon.strip.pstr_name = _af_pack_string( NLAStrip.name )
             _ms_compiler.strips.append( out_strip )
          #}
       #}
@@ -467,12 +481,12 @@ def _metascene_camera_anims( obj, entity_id ):
             print( F"    have strip {NLAStrip.name}" )
             out_strip = ms_strip()
             _metascene_compile_action_curves( out_strip, NLAStrip.action )
-            out_strip.instance_id = 0xffffffff
-            out_strip.object_id = entity_id
-            out_strip.offset = math.floor( NLAStrip.frame_start )
-            out_strip.timing_offset = NLAStrip.action_frame_start
-            out_strip.length = math.ceil( NLAStrip.frame_end - out_strip.offset )
-            out_strip.pstr_name = _af_pack_string( NLAStrip.name )
+            out_strip.anon.strip.instance_id = 0xffffffff
+            out_strip.anon.strip.object_id = entity_id
+            out_strip.anon.strip.offset = math.floor( NLAStrip.frame_start )
+            out_strip.anon.strip.timing_offset = NLAStrip.action_frame_start
+            out_strip.anon.strip.length = math.ceil( NLAStrip.frame_end - out_strip.offset )
+            out_strip.anon.strip.pstr_name = _af_pack_string( NLAStrip.name )
             _ms_compiler.strips.append( out_strip )
          #}
       #}
@@ -600,15 +614,26 @@ def _sr_export_metascene( path ):
    #{
       print( F"Marker {marker.name}: {marker.camera}" )
       out_strip = ms_strip()
-      out_strip.data_start = 0
-      out_strip.data_count = 0
-      out_strip.data_mode = 2
+      out_strip.mode = 0x10 << int(marker.SR_data.tipo)
       out_strip.offset = marker.frame
-      out_strip.length = 0
-      out_strip.pstr_name = _af_pack_string( marker.name )
-      out_strip.pstr_internal_name = 0
-      out_strip.instance_id = 0xffffffff
-      out_strip.object_id = sr_entity_id( marker.camera )
+
+      if out_strip.mode == 0x10:
+      #{
+         out_strip.anon.camera.entity_id = sr_entity_id( marker.camera )
+         print( out_strip.anon.camera.entity_id )
+      #}
+
+      if out_strip.mode == 0x20:
+      #{
+         out_strip.anon.event.pstr_string = _af_pack_string( marker.SR_data.event_string )
+      #}
+
+      if out_strip.mode == 0x40:
+      #{
+         out_strip.anon.subtitle.pstr_en = _af_pack_string( marker.SR_data.subtitle_en.replace('\\n','\n') )
+         out_strip.anon.subtitle.character = int( marker.SR_data.subtitle_person )
+      #}
+
       _ms_compiler.strips.append( out_strip )
    #}
 
diff --git a/src/2 b/src/2
new file mode 100644 (file)
index 0000000..4946ea0
--- /dev/null
+++ b/src/2
@@ -0,0 +1,85 @@
+static bool _skaterift_script_valley( ent_script_event *event )
+{
+   if( on_nugget_once( event, "ch4s1a_view" ) )
+   {
+      /* ch4s1: Mike and you are first encountering the valley world */
+      static const struct cs_subtitle EN[] = 
+      {
+         { "m1",  KCOL_MIKE "It's gotta be some kind of dream right?" },
+         { "m2",  KCOL_MIKE "I mean... Cambodia?" },
+         { "m3",  KCOL_MIKE "What are we even doing here?" },
+         { NULL, NULL },
+      };
+      _cutscene_load_and_play( "metascenes/ch4s1a.ms", EN, 1 );
+   }
+
+   /* main region is completed (this is just the time trial as of 14.05.25, unlock ch4s2 */
+   if( on_function_trigger( event, 27 ) )
+   {
+      if( _skaterift_script_nugget_status( "ch4s2_view" ) == 0 )
+         _skaterift_script_nugget_set( "ch4s2_view", 2 );
+   }
+
+   /* unlock the finale challenge stuff if we've seen ch4s1 (mike bails) */
+   u64 status;
+   if( on_nugget_changed( event, "ch4s1_view", &status ) )
+   {
+      _ent_list_set_visible( _ent_list_get_aliased( "finale:locked" ),   status != 1 );
+      _ent_list_set_visible( _ent_list_get_aliased( "finale:unlocked" ), status == 1 );
+   }
+
+   /* finale completed, trigger the exit movie */
+   if( on_function_trigger( event, 21 ) )
+   {
+      // TODOX1
+      vg_success( "Exit for a movie\n" );
+   }
+
+   return 1;
+}
+
+static bool _skaterift_script_ch4s2( ent_script_event *event )
+{
+   /* ch4s2: Mike and you find the rocket, and talk to the FBI person. */
+   u64 status;
+   if( on_nugget_changed( event, "ch4s2_view", &status ) )
+   {
+      _ent_list_set_visible( event->entity_list, status == 2 );
+      _ent_list_set_visible( _ent_list_get_aliased( "rocket" ), status >= 1 );
+   }
+
+   if( on_function_trigger( event, 0 ) )
+   {
+      if( on_nugget_once( event, "ch4s2_view" ) )
+      {
+         static const struct cs_subtitle EN[] = 
+         {
+            { "m1",  KCOL_MIKE "What the hell is that thing?" },
+            { "f1",  KCOL_FBI  "Look man, all they told is that uhh" },
+            { "f2",  KCOL_FBI  "they're sending you up to one of saturns moons.." },
+            { "f3",  KCOL_FBI  "On that thing." },
+            { "f4",  KCOL_FBI  "To help you on your mission." },
+            { "f5",  KCOL_FBI  "You guys are more important than any person on earth right now" },
+            { "f6",  KCOL_FBI  "According to the president." },
+            { "f7",  KCOL_FBI  "But obviously this is some kind of joke I'm not in on." },
+            { "f8",  KCOL_FBI  "I don't believe a word of it." },
+            { NULL, NULL },
+         };
+         _cutscene_load_and_play( "metascenes/ch4s2.ms", EN, 1 );
+      }
+   }
+
+   return 1;
+}
+
+static bool _skaterift_script_ch4s1( ent_script_event *event )
+{
+   /* ch4s1: (Yes, this comes after ch4s2), Mike is leaving, because JC hasn't shown up anywhere. */
+   return 1;
+}
+
+static bool _skaterift_script_ch4s3( ent_script_event *event )
+{
+   // on venus
+   return 1;
+}
index b3aa492d2a3258bf30013aeeb041eb6a7000780a..02bbae26c8d4e683ddbeba3dc9f0b05cb4c85b2d 100644 (file)
@@ -5,29 +5,30 @@
 #include "audio.h"
 #include "ent_region.h"
 
-void _ent_challenge_complete( ent_challenge *challenge )
+void _ent_challenge_clear( ent_challenge *challenge )
 {
    world_instance *world = &_world.main;
-   vg_info( "challenge( '%s' )\n", af_str( &world->meta.af, challenge->pstr_alias) );
-   if( challenge->on_complete_id )
+   u32 next = challenge->first_objective_id;
+   while( mdl_entity_id_type(next) == k_ent_objective )
    {
-      ent_call call;
-      call.data = NULL;
-      call.function = challenge->on_complete_event;
-      call.id = challenge->on_complete_id;
-      entity_call( world, &call );
+      u32 index = mdl_entity_id_id( next );
+      ent_objective *objective = af_arritm(&world->ent_objective,index);
+      objective->flags |= k_ent_objective_hidden;
+      next = objective->id_next;
    }
-
-   challenge->status = 1;
 }
 
 void _ent_challenge_win(void)
 {
+   _world_raise_event( _world.active_challenge_id, "complete" );
+
    world_instance *world = &_world.main;
    ent_challenge *challenge = af_arritm( &world->ent_challenge, mdl_entity_id_id( _world.active_challenge_id ) );
-   _ent_challenge_complete( challenge );
+   _ent_challenge_clear( challenge );
+   challenge->status = 1;
    ent_region_re_eval( world );
 
+#if 0
    struct ent_script_event event;
    struct script_event_completion_changed inf = {
       .entity_id = _world.active_challenge_id,
@@ -36,6 +37,7 @@ void _ent_challenge_win(void)
    event.type = k_escript_event_completion_changed;
    event.info = &inf;
    ent_script_propogate_event( world, &event );
+#endif
 
    if( world_clear_event( k_world_event_challenge ) )
    {
@@ -45,56 +47,30 @@ void _ent_challenge_win(void)
    }
 }
 
-entity_call_result ent_challenge_call( world_instance *world, ent_call *call )
+entity_event_result ent_challenge_event( ent_event *event )
 {
-   u32 index = mdl_entity_id_id( call->id );
-   ent_challenge *challenge = af_arritm( &world->ent_challenge, index );
-
-   if( (_world.event == k_world_event_challenge) && (_world.challenge_state >= k_challenge_state_running) )
-   {
-      return k_entity_call_result_OK;
-   }
-   else
+   world_instance *world = &_world.main;
+   ent_challenge *challenge = af_arritm( &world->ent_challenge, mdl_entity_id_id( event->recieve_entity_id ) );
+   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "view" ) )
    {
-      if( call->function == 1 ) /* view() */
+      if( world_set_event( k_world_event_challenge ) )
       {
-         if( localplayer.subsystem == k_player_subsystem_walk )
-         {
-            if( !(challenge->flags & k_ent_challenge_locked) )
-            {
-               if( world_set_event( k_world_event_challenge ) )
-               {
-                  _world.challenge_state = k_challenge_state_none;
-                  _world.active_challenge_id = call->id;
-                  gui_helper_reset( 1 );
-                  vg_str text;
-                  if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
-                     vg_strcat( &text, "View Challenge" );
-               }
-            }
-         }
+         srinput.state = k_input_state_resume;
+         gui_helper_reset( k_gui_helper_mode_clear );
+         vg_str text;
+         if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
+            vg_strcat( &text, "Start" );
+         if( gui_new_helper( input_button_list[k_srbind_mback], &text ))
+            vg_strcat( &text, "Exit" );
 
-         return k_entity_call_result_OK;
-      }
-      else if( call->function == -1 ) /* unview() */
-      {
-         if( _world.challenge_state < k_challenge_state_running )
-         {
-            if( !(challenge->flags & k_ent_challenge_locked) )
-            {
-               if( world_clear_event( k_world_event_challenge ) )
-               {
-                  _world.challenge_state = k_challenge_state_none;
-                  _world.active_challenge_id = 0;
-                  gui_helper_reset( k_gui_helper_mode_clear );
-               }
-            }
-         }
-         return k_entity_call_result_OK;
+         localplayer.immobile = 1;
+         menu.disable_open = 1;
+         _world.challenge_state = k_challenge_state_viewing;
+         _world.active_challenge_id = event->recieve_entity_id;
       }
-      else
-         return k_entity_call_result_unhandled;
+      return k_entity_event_result_OK;
    }
+   else return k_entity_event_result_unhandled;
 }
 
 void _restart_active_challenge(void)
@@ -116,7 +92,7 @@ void _restart_active_challenge(void)
    {
       u32 index = mdl_entity_id_id( next );
       ent_objective *objective = af_arritm(&world->ent_objective,index);
-      objective->flags &= ~(k_ent_objective_passed|k_ent_objective_failed);
+      objective->flags &= ~(k_ent_objective_passed|k_ent_objective_failed|k_ent_objective_hidden);
       next = objective->id_next;
       v3_fill( objective->transform.s, 1.0f );
    }
@@ -184,24 +160,21 @@ void ent_challenge_update(void)
          localplayer.immobile = 0; /* TODO: Unify this probably after eating some potats */
          menu.disable_open = 0;
 
-         _restart_active_challenge();
-
-         if( challenge->on_activate_id )
-         {
-            ent_call call;
-            call.data = NULL;
-            call.function = challenge->on_activate_event;
-            call.id = challenge->on_activate_id;
-            entity_call( &_world.main, &call );
-         }
+         _world_raise_event( _world.active_challenge_id, "activate" );
       }
       else if( button_down( k_srbind_mback ) )
       {
-         gui_helper_reset( k_gui_helper_mode_clear );
-         _world.challenge_state = k_challenge_state_none;
-         localplayer.immobile = 0; /* TODO: Unify this probably after eating some potats */
-         menu.disable_open = 0;
-         srinput.state = k_input_state_resume;
+         if( world_clear_event( k_world_event_challenge ) )
+         {
+            _world.active_challenge_id = 0;
+            _world.challenge_target = NULL;
+            _world.challenge_timer = 0.0f;
+            gui_helper_reset( k_gui_helper_mode_clear );
+            _world.challenge_state = k_challenge_state_none;
+            localplayer.immobile = 0; /* TODO: Unify this probably after eating some potats */
+            menu.disable_open = 0;
+            srinput.state = k_input_state_resume;
+         }
       }
    }
    else if( _world.challenge_state == k_challenge_state_running )
@@ -224,10 +197,15 @@ void ent_challenge_update(void)
       }
 
       f32 max_dist = 100.0f;
+      if( localplayer.subsystem == k_player_subsystem_glide )
+         max_dist = 500.0f;
+
       if( min_dist2 > max_dist*max_dist )
       {
          if( world_clear_event( k_world_event_challenge ) )
          {
+            _ent_challenge_clear( challenge );
+
             _world.active_challenge_id = 0;
             _world.challenge_target = NULL;
             _world.challenge_timer = 0.0f;
@@ -241,21 +219,6 @@ void ent_challenge_update(void)
    }
    else if( _world.challenge_state == k_challenge_state_none )
    {
-      if( button_down( k_srbind_maccept ) )
-      {
-         srinput.state = k_input_state_resume;
-         gui_helper_reset( k_gui_helper_mode_clear );
-         vg_str text;
-         if( gui_new_helper( input_button_list[k_srbind_maccept], &text ))
-            vg_strcat( &text, "Start" );
-         if( gui_new_helper( input_button_list[k_srbind_mback], &text ))
-            vg_strcat( &text, "Exit" );
-
-         localplayer.immobile = 1;
-         menu.disable_open = 1;
-         srinput.state = k_input_state_resume;
-         _world.challenge_state = k_challenge_state_viewing;
-      }
    }
 
    if( _world.challenge_state >= k_challenge_state_running )
index 88aef576bbab1163ced999081b5aaed86c311c41..4c4b6fdb1e7eeadfd8722ad149960d958e17f015 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once
 #include "entity.h"
 
-entity_call_result ent_challenge_call( world_instance *world, ent_call *call );
+entity_event_result ent_challenge_event( ent_event *event );
 void _ent_challenge_ui( ui_context *ctx );
 void _restart_active_challenge(void);
 void _ent_challenge_complete( ent_challenge *challenge );
index 2148b3dd099b7399330823b8ffd694644be77673..60e599a9422b63e46c692114f091d22d03dd0b7d 100644 (file)
@@ -2,24 +2,29 @@
 #include "entity.h"
 #include "player_glide.h"
 
-entity_call_result ent_glider_call( world_instance *world, ent_call *call )
+entity_event_result ent_glider_event( ent_event *event )
 {
-   u32 index = mdl_entity_id_id( call->id );
-   ent_glider *glider = af_arritm( &world->ent_glider, index );
-
-   if( call->function == 0 )
+   world_instance *world = &_world.main;
+   ent_glider *glider = af_arritm( &world->ent_glider, mdl_entity_id_id( event->recieve_entity_id ) );
+   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "lock" ) )
    {
-      glider->flags |= 0x1;
-      return k_entity_call_result_OK;
+      // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
+      if( event->flags == k_ent_event_data_const_i32 )
+      {
+         if( event->data.const_i32 ) glider->flags &= ~((u32)1);
+         else                        glider->flags |=   (u32)1;
+         return k_entity_event_result_OK;
+      }
+      else
+         return k_entity_event_result_invalid;
    }
-   else if( call->function == 1 )
+   else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "equip" ) )
    {
       if( glider->flags & 0x1 )
-      {
          player_glide_equip_glider();
-      }
-      return k_entity_call_result_OK;
+
+      return k_entity_event_result_OK;
    }
    else 
-      return k_entity_call_result_unhandled;
+      return k_entity_event_result_unhandled;
 }
index 5815ddafb309e5796b121353a4d3d35f915c0f16..d92b4d25f5ad813073b3139a8c6a0712ea410f03 100644 (file)
@@ -1,4 +1,4 @@
 #pragma once
 #include "entity.h"
 
-entity_call_result ent_glider_call( world_instance *world, ent_call *call );
+entity_event_result ent_glider_call( ent_event *event );
index 2dd69a8897685f49d56bb45a1240f274607741ba..e2f47013fe154143b6b655d3ba3c8cbc83af38dd 100644 (file)
@@ -84,6 +84,61 @@ void _ent_list_set_visible( ent_list *list, bool visible )
          if( visible ) marker->flags &= ~((u32)k_ent_marker_flag_hidden);
          else          marker->flags |=   (u32)k_ent_marker_flag_hidden;
       }
+      else if( iter.type == k_ent_glider )
+      {
+         ent_glider *glider = af_arritm( &world->ent_glider, iter.index );
+         if( visible ) glider->flags |= 0x1;
+         else          glider->flags &= ~((u32)0x1);
+      }
+   }
+}
+
+bool _ent_list_check_completed( ent_list *list )
+{
+   world_instance *world = &_world.main;
+   struct ent_list_iter iter;
+   _ent_list_iter_start( &iter, list, 0 );
+
+   while( _ent_list_iter( &iter ) )
+   {
+      if( iter.type == k_ent_challenge )
+      {
+         ent_challenge *challenge = af_arritm( &world->ent_challenge, iter.index );
+         if( challenge->status == 0 )
+            return 0;
+      }
+      else if( iter.type == k_ent_route )
+      {
+         ent_route *route = af_arritm( &world->ent_route, iter.index );
+         if( !(route->flags & (k_ent_route_flag_achieve_silver|k_ent_route_flag_achieve_gold)) )
+            return 0;
+      }
    }
+
+   return 1;
 }
 
+void _ent_list_set_as_targets( ent_list *list, bool yes )
+{
+#if 0
+   world_instance *world = &_world.main;
+   struct ent_list_iter iter;
+   _ent_list_iter_start( &iter, list, 0 );
+
+   while( _ent_list_iter( &iter ) )
+   {
+      if( iter.type == k_ent_challenge )
+      {
+         ent_challenge *challenge = af_arritm( &world->ent_challenge, iter.index );
+         if( yes ) challenge->flags |=   (u32)k_ent_challenge_target;
+         else      challenge->flags &= ~((u32)k_ent_challenge_target);
+      }
+      else if( iter.type == k_ent_route )
+      {
+         ent_route *route = af_arritm( &world->ent_route, iter.index );
+         if( yes ) route->flags |=   (u32)k_ent_route_target;
+         else      route->flags &= ~((u32)k_ent_route_target);
+      }
+   }
+#endif
+}
index 311b0fee388664f67aad37d9145da722a3271c47..269890f5d8f93b822d4f56db22d67f0ebbfe5b6b 100644 (file)
@@ -31,7 +31,8 @@ struct
       player_pose pose;
       m4x3f *final_mtx;
    }
-   jc, mike;
+   humans[4];
+
    struct skeleton_anim anim_idle;
 
    enum npc_sub_state
@@ -47,10 +48,18 @@ struct
 }
 _npc;
 
-void _ent_npc_set_in_cutscene( enum npc npc_id, bool yes )
+static struct human_npc *human_npc( enum npc id )
+{
+   if( (id > 0) && (id <= k_npc_human_reserved) )
+      return &_npc.humans[ id-1 ];
+   else return NULL;
+}
+
+void _ent_npc_set_in_cutscene( enum npc id, bool yes )
 {
-   if( npc_id == k_npc_jc )
-      _npc.jc.in_cutscene = yes;
+   struct human_npc *human = human_npc(id);
+   if( human )
+      human->in_cutscene = yes;
 }
 
 struct sub_context
@@ -59,114 +68,145 @@ struct sub_context
    u32 alias_hash;
    const cs_subtitle *subtitles;
 }
-static _gino_contexts[] =
+static *_sub_contexts[] =
 {
-   /* HEAVEN world */
+   [ k_npc_gino ] = (struct sub_context[])
    {
-      "heaven:introduction", .subtitles = (const cs_subtitle[]) 
+      /* HEAVEN world */
       {
-         { "a1", KCOL_JESUS "Hmm.. I'm Gino, hello" },
-         { "a2", KCOL_JESUS "Do you remember who you are?" },
-         { "a3", KCOL_JESUS "Pick here.." },
-         { NULL, NULL },
+         "heaven:introduction", .subtitles = (const cs_subtitle[]) 
+         {
+            { "a1", KCOL_JESUS "Hmm.. I'm Gino, hello" },
+            { "a2", KCOL_JESUS "Do you remember who you are?" },
+            { "a3", KCOL_JESUS "Pick here.." },
+            { NULL, NULL },
+         },
       },
-   },
-   {
-      "heaven:locked", .subtitles = (const cs_subtitle[]) 
       {
-         { "a1", KCOL_JESUS "Welcome to almost Heaven.." },
-         { "a2", KCOL_JESUS "The entrance is blocked.." },
-         { "a3", KCOL_JESUS "You'll go back to earth for now.." },
-         { "a4", KCOL_JESUS "There are people waiting for you.." },
-         { "a5", KCOL_JESUS "I think.." },
-         { NULL, NULL },
-      }
-   },
-   {
-      "heaven:shop", .subtitles = (const cs_subtitle[]) 
+         "heaven:locked", .subtitles = (const cs_subtitle[]) 
+         {
+            { "a1", KCOL_JESUS "Welcome to almost Heaven.." },
+            { "a2", KCOL_JESUS "The entrance is blocked.." },
+            { "a3", KCOL_JESUS "You'll go back to earth for now.." },
+            { "a4", KCOL_JESUS "There are people waiting for you.." },
+            { "a5", KCOL_JESUS "I think.." },
+            { NULL, NULL },
+         }
+      },
       {
-         { "a1", KCOL_JESUS "Might want to pick up one of these.." },
-         { "a2", KCOL_JESUS "See you at the center Island.." },
-         { NULL, NULL },
-      }
-   },
+         "heaven:shop", .subtitles = (const cs_subtitle[]) 
+         {
+            { "a1", KCOL_JESUS "Might want to pick up one of these.." },
+            { "a2", KCOL_JESUS "See you at the center Island.." },
+            { NULL, NULL },
+         }
+      },
 
-   /* HUB world */
-   { 
-      "mtzero:locked", .subtitles = (const cs_subtitle[]) 
-      {
-         { "a1", KCOL_JESUS "Someone put boxes here.." },
-         { "a2", KCOL_JESUS "Hmm.." },
-         { NULL, NULL },
-      }
-   },
-   {
-      "city:locked", .subtitles = (const cs_subtitle[]) 
+      /* HUB world */
+      { 
+         "mtzero:locked", .subtitles = (const cs_subtitle[]) 
+         {
+            { "a1", KCOL_JESUS "Someone put boxes here.." },
+            { "a2", KCOL_JESUS "Hmm.." },
+            { NULL, NULL },
+         }
+      },
       {
-         { "a1", KCOL_JESUS "Again with the boxes!" },
-         { "a2", KCOL_JESUS "Who is doing that?" },
-         { NULL, NULL },
-      }
-   },
-   {
-      "valley:locked", .subtitles = (const cs_subtitle[]) 
+         "city:locked", .subtitles = (const cs_subtitle[]) 
+         {
+            { "a1", KCOL_JESUS "Again with the boxes!" },
+            { "a2", KCOL_JESUS "Who is doing that?" },
+            { NULL, NULL },
+         }
+      },
       {
-         { "a1", KCOL_JESUS ".." },
-         { "a2", KCOL_JESUS "You know what to do.." },
-         { NULL, NULL },
-      }
-   },
-   {
-      "boardmaker", .subtitles = (const cs_subtitle[]) 
+         "valley:locked", .subtitles = (const cs_subtitle[]) 
+         {
+            { "a1", KCOL_JESUS ".." },
+            { "a2", KCOL_JESUS "You know what to do.." },
+            { NULL, NULL },
+         }
+      },
       {
-         { "a1", KCOL_JESUS "Now that you know how to make boards" },
-         { "a2", KCOL_JESUS "We moved a workshop in upstairs.." },
-         { "a3", KCOL_JESUS ":)" },
-         { NULL, NULL },
-      }
-   },
+         "boardmaker", .subtitles = (const cs_subtitle[]) 
+         {
+            { "a1", KCOL_JESUS "Now that you know how to make boards" },
+            { "a2", KCOL_JESUS "We moved a workshop in upstairs.." },
+            { "a3", KCOL_JESUS ":)" },
+            { NULL, NULL },
+         }
+      },
 
-   /* VOLCANO world */
-   { 
-      "docks:locked", .subtitles = (const cs_subtitle[]) 
-      {
-         { "a1", KCOL_JESUS "To get to the docks.." },
-         { "a2", KCOL_JESUS "Hmm.." },
-         { "a3", KCOL_JESUS "JC demands you do all the tasks here.." },
-         { "a4", KCOL_JESUS "Before going home.." },
-         { "a5", KCOL_JESUS "Take a look at the map.." },
-         { NULL, NULL },
-      }
-   },
+      /* VOLCANO world */
+      
+         "docks:locked", .subtitles = (const cs_subtitle[]) 
+         {
+            { "a1", KCOL_JESUS "To get to the docks.." },
+            { "a2", KCOL_JESUS "Hmm.." },
+            { "a3", KCOL_JESUS "JC demands you do all the tasks here.." },
+            { "a4", KCOL_JESUS "Before going home.." },
+            { "a5", KCOL_JESUS "Take a look at the map.." },
+            { NULL, NULL },
+         }
+      },
 
-   /* MTZERO WORLD */
-   { 
-      "battery:locked", .subtitles = (const cs_subtitle[]) 
+      /* MTZERO WORLD */
+      { 
+         "battery:locked", .subtitles = (const cs_subtitle[]) 
+         {
+            { "a1", KCOL_JESUS "See that..?" },
+            { "a2", KCOL_JESUS "Hmm.." },
+            { "a3", KCOL_JESUS "Big ramp over there.." },
+            { NULL, NULL },
+         }
+      },
+      { NULL }
+   },
+   [ k_npc_jc ] = (struct sub_context[])
+   {
       {
-         { "a1", KCOL_JESUS "See that..?" },
-         { "a2", KCOL_JESUS "Hmm.." },
-         { "a3", KCOL_JESUS "Big ramp over there.." },
-         { NULL, NULL },
-      }
+         "jc:demo", .subtitles = (const cs_subtitle[]) 
+         {
+            { "a1", KCOL_JOHN  "HELLO I AM JC" },
+            { "a2", KCOL_JOHN  "JC" },
+            { "a3", KCOL_JOHN  "IS ME" },
+            { NULL, NULL },
+         },
+      },
+      { NULL }
    },
-},
-_jc_contexts[] =
-{
+   [ k_npc_mike ] = (struct sub_context[])
    {
-      "jc:demo", .subtitles = (const cs_subtitle[]) 
       {
-         { "a1", KCOL_JOHN  "HELLO I AM JC" },
-         { "a2", KCOL_JOHN  "JC" },
-         { "a3", KCOL_JOHN  "IS ME" },
-         { NULL, NULL },
+         "mike:demo", .subtitles = (const cs_subtitle[]) 
+         {
+            { "a1", KCOL_MIKE  "HELLO I AM MIKE" },
+            { "a2", KCOL_MIKE  "MIKE" },
+            { "a3", KCOL_MIKE  "IS ME" },
+            { NULL, NULL },
+         },
       },
+      { NULL }
    },
 };
 
 void _ent_npc_init(void)
 {
-   for( u32 i=0; i<VG_ARRAY_LEN(_gino_contexts); i ++ )
-      _gino_contexts[i].alias_hash = vg_strdjb2( _gino_contexts[i].alias );
+   for( u32 i=0; i<k_npc_max; i ++ )
+   {
+      struct sub_context *contexts = _sub_contexts[ i ];
+      if( !contexts )
+         continue;
+
+      for( u32 i=0; i<1000; i ++ )
+      {
+         struct sub_context *context = &contexts[i];
+         if( context->alias == NULL )
+            break;
+
+         context->alias_hash = vg_strdjb2( context->alias );
+      }
+   }
 
    void *alloc = vg_mem.rtmemory;
    mdl_context *mdl = &_npc.gino.mdl;
@@ -180,8 +220,11 @@ void _ent_npc_init(void)
 
    struct skeleton *sk = &localplayer.skeleton;
    u32 mtx_size = sizeof(m4x3f)*sk->bone_count;
-   _npc.jc.final_mtx = vg_linear_alloc( alloc, mtx_size );
-   _npc.mike.final_mtx = vg_linear_alloc( alloc, mtx_size );
+   for( u32 i=0; i<4; i ++ )
+   {
+      struct human_npc *human = &_npc.humans[i];
+      human->final_mtx = vg_linear_alloc( alloc, mtx_size );
+   }
    player_get_anim( &_npc.anim_idle, "idle_lean+y" );
 }
 
@@ -192,20 +235,52 @@ void _ent_npc_reset(void)
    _npc.gino.command_t = 0.0;
    _npc.gino.current_entity_id = 0;
 
-   _npc.jc.alive = 0;
-   _npc.mike.alive = 0;
-   addon_cache_unwatch( k_addon_type_player, _npc.jc.playermodel_view_slot );
-   addon_cache_unwatch( k_addon_type_player, _npc.mike.playermodel_view_slot );
+   for( u32 i=0; i<4; i++ )
+   {
+      struct human_npc *human = &_npc.humans[i];
+      human->alive = 0;
+      addon_cache_unwatch( k_addon_type_player, human->playermodel_view_slot );
+   }
 }
 
-void _ent_npc_speech( enum npc npc_id, const cs_subtitle *subs )
+void _ent_npc_speech( enum npc npc_id, const char *speech_alias )
 {
+   const char *alias = speech_alias;
+   u32 hash = vg_strdjb2( alias );
+
+   struct sub_context *contexts = _sub_contexts[ npc_id ];
+   if( !contexts )
+   {
+      vg_error( "npc_id %d has no speech contexts, but speech for '%s' was requested.\n", npc_id, speech_alias );
+      return;
+   }
+
+   const cs_subtitle *subtitles = NULL;
+   for( u32 i=0; i<1000; i ++ )
+   {
+      struct sub_context *context = &contexts[i];
+      if( context->alias == NULL )
+      {
+         vg_error( "npc_id %d does not contain speech set '%s'\n", npc_id, speech_alias );
+         return;
+      }
+
+      if( (hash == context->alias_hash) && !strcmp(context->alias,alias) )
+      {
+         subtitles = context->subtitles;
+         break;
+      }
+   }
+
+   if( !subtitles )
+      vg_fatal_error( "You fucked the context array up good job\n" );
+
    srinput.state = k_input_state_resume;
-   if( _npc.subtitles != subs )
+   if( _npc.subtitles != subtitles )
    {
       _npc.sub_state = k_npc_sub_off;
       _npc.sub_index = 0;
-      _npc.subtitles = subs;
+      _npc.subtitles = subtitles;
    }
 
    if( _npc.sub_state == k_npc_sub_reading )
@@ -295,20 +370,25 @@ void _ent_npc_preupdate(void)
       }
    }
 
-   if( _npc.jc.alive && (v3_dist2( localplayer.rb.co, _npc.jc.co ) < 40.0f*40.0f) )
+   for( u32 i=0; i<4; i ++ )
    {
-      ms_keyframe apose[32], bpose[32];
-      struct skeleton *sk = &localplayer.skeleton;
-      player_pose *pose = &_npc.jc.pose;
-      pose->type = k_player_pose_type_ik;
-      pose->board.lean = 0.0f;
-      v3_copy( _npc.jc.co, pose->root_co );
-      v4_copy( _npc.jc.q, pose->root_q );
-      skeleton_sample_anim( sk, &_npc.anim_idle, vg.time*0.1f+0.4f, apose );
-      skeleton_copy_pose( sk, apose, pose->keyframes );
-      // no for JC.
-      // effect_blink_apply( &_npc.jc.effect_data.blink, pose, vg.time_delta );
-      apply_full_skeleton_pose( sk, pose, _npc.jc.final_mtx );
+      struct human_npc *human = &_npc.humans[i];
+      if( human->alive && (v3_dist2( localplayer.rb.co, human->co ) < 40.0f*40.0f) )
+      {
+         ms_keyframe apose[32], bpose[32];
+         struct skeleton *sk = &localplayer.skeleton;
+         player_pose *pose = &human->pose;
+         pose->type = k_player_pose_type_ik;
+         pose->board.lean = 0.0f;
+         v3_copy( human->co, pose->root_co );
+         v4_copy( human->q, pose->root_q );
+         skeleton_sample_anim( sk, &_npc.anim_idle, vg.time*0.1f+0.4f, apose );
+         skeleton_copy_pose( sk, apose, pose->keyframes );
+         // no for JC.
+         if( i != (k_npc_jc-1) )
+            effect_blink_apply( &human->effect_data.blink, pose, vg.time_delta );
+         apply_full_skeleton_pose( sk, pose, human->final_mtx );
+      }
    }
 }
 
@@ -316,14 +396,18 @@ void _ent_npc_render( vg_camera *cam )
 {
    world_instance *world = &_world.main;
 
-   if( _npc.jc.alive && (v3_dist2( localplayer.rb.co, _npc.jc.co ) < 40.0f*40.0f) )
+   for( u32 i=0; i<4; i ++ )
    {
-      if( !((_cutscene.state == k_cutscene_state_playing) && _npc.jc.in_cutscene) )
+      struct human_npc *human = &_npc.humans[i];
+      if( human->alive && (v3_dist2( localplayer.rb.co, human->co ) < 40.0f*40.0f) )
       {
-         m4x3f *final_mtx = _npc.jc.final_mtx;
-         struct player_model *model = addon_cache_item_data( k_addon_type_player, _npc.jc.playermodel_view_slot, 1 );
-         struct skeleton *sk = &localplayer.skeleton;
-         render_playermodel( cam, world, 0, model, sk, final_mtx );
+         if( !((_cutscene.state == k_cutscene_state_playing) && human->in_cutscene) )
+         {
+            m4x3f *final_mtx = human->final_mtx;
+            struct player_model *model = addon_cache_item_data( k_addon_type_player, human->playermodel_view_slot, 1 );
+            struct skeleton *sk = &localplayer.skeleton;
+            render_playermodel( cam, world, 0, model, sk, final_mtx );
+         }
       }
    }
 
@@ -383,28 +467,52 @@ void _ent_npc_render( vg_camera *cam )
    mdl_draw_submesh( &_npc.gino.mdl.submeshes[ _npc.gino.sm_hat ] );
 }
 
-entity_call_result ent_npc_call( world_instance *world, ent_call *call )
+entity_event_result ent_npc_event( ent_event *event )
 {
-   u32 index = mdl_entity_id_id( call->id );
-   ent_npc *npc = af_arritm( &world->ent_npc, index );
+   world_instance *world = &_world.main;
+   ent_npc *npc = af_arritm( &world->ent_npc, mdl_entity_id_id( event->recieve_entity_id ) );
+
+   const char *npc_aliases[] = 
+   {
+      [k_npc_gino] = "gino",
+      [k_npc_jc] = "JC",
+      [k_npc_mike] = "mike",
+      [k_npc_fbi] = "fbi",
+      [k_npc_max] = NULL
+   };
+
+   enum npc npc_id = k_npc_none;
+
+   for( u32 i=0; i<k_npc_max; i ++ )
+   {
+      if( npc_aliases[i] )
+      {
+         if( AF_STR_EQ( &world->meta.af, npc->pstr_id, npc_aliases[i] ) )
+         {
+             npc_id = i;
+             break;
+         }
+      }
+   }
 
-        if( AF_STR_EQ( &world->meta.af, npc->pstr_id, "gino" ) )
+   if( npc_id == k_npc_none )
    {
-      /* interact */
-      if( call->function == 0 )
+      vg_warn( "No npc with alias: %s\n", af_str( &world->meta.af, npc->pstr_id ) );
+      return k_entity_event_result_invalid;
+   }
+
+   if( npc_id == k_npc_gino )
+   {
+      if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "interact" ) )
       {
-         const char *alias = af_str( &world->meta.af, npc->pstr_context_id );
-         u32 hash = vg_strdjb2( alias );
-         for( u32 i=0; i<VG_ARRAY_LEN(_gino_contexts); i ++ )
-            if( (hash == _gino_contexts[i].alias_hash) && !strcmp(_gino_contexts[i].alias,alias) )
-               _ent_npc_speech( k_npc_gino, _gino_contexts[i].subtitles );
+         _ent_npc_speech( npc_id, af_str( &world->meta.af, npc->pstr_context_id ) );
+         return k_entity_event_result_OK;
       }
-      /* proximity */
-      else if( call->function == 1 )
+      else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "proximity" ) )
       {
-         if( _npc.gino.current_entity_id != call->id )
+         if( _npc.gino.current_entity_id != event->source_entity_id )
          {
-            _npc.gino.current_entity_id = call->id;
+            _npc.gino.current_entity_id = event->source_entity_id;
             v3_copy( npc->transform.co, _npc.gino.p1 );
             if( _npc.gino.state == k_gino_none )
                v3_add( npc->transform.co, (v3f){0,30,0}, _npc.gino.p0 );
@@ -414,33 +522,37 @@ entity_call_result ent_npc_call( world_instance *world, ent_call *call )
             _npc.gino.state = k_gino_intro;
             _npc.gino.command_t = vg.time;
          }
+         return k_entity_event_result_OK;
       }
-
-      return k_entity_call_result_OK;
+      else return k_entity_event_result_unhandled;
    }
-   else if( AF_STR_EQ( &world->meta.af, npc->pstr_id, "JC" ) )
+   else
    {
-      if( call->function == 0 )
+      struct human_npc *human = human_npc( npc_id );
+      VG_ASSERT( human );
+
+      if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "interact" ) )
       {
-         const char *alias = af_str( &world->meta.af, npc->pstr_context_id );
-         u32 hash = vg_strdjb2( alias );
-         for( u32 i=0; i<VG_ARRAY_LEN(_jc_contexts); i ++ )
-            if( (hash == _jc_contexts[i].alias_hash) && !strcmp(_jc_contexts[i].alias,alias) )
-               _ent_npc_speech( k_npc_gino, _jc_contexts[i].subtitles );
+         _ent_npc_speech( npc_id, af_str( &world->meta.af, npc->pstr_context_id ) );
+         return k_entity_event_result_OK;
       }
-      /* proximity */
-      else if( call->function == 1 )
+      else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "proximity" ) )
       {
-         if( _npc.jc.alive == 0 )
+         if( human->alive == 0 )
          {
-            _npc.jc.alive = 1;
-            _npc.jc.playermodel_view_slot = addon_cache_create_viewer_from_uid( k_addon_type_player, "sr003-local-skaterift_john" );
+            const char *addons[] = 
+            {
+               [k_npc_jc] = "sr003-local-skaterift_john",
+               [k_npc_mike] = "sr003-local-skaterift_mike",
+               [k_npc_fbi] = "sr003-local-skaterift_fbi",
+            };
+            human->alive = 1;
+            human->playermodel_view_slot = addon_cache_create_viewer_from_uid( k_addon_type_player, addons[npc_id] );
          }
-         v3_copy( npc->transform.co, _npc.jc.co );
-         q_copy( npc->transform.q, _npc.jc.q );
+         v3_copy( npc->transform.co, human->co );
+         q_copy( npc->transform.q, human->q );
+         return k_entity_event_result_OK;
       }
-      return k_entity_call_result_OK;
+      else return k_entity_event_result_unhandled;
    }
-
-   return k_entity_call_result_unhandled;
 }
index 21e5e3db5c9b8bec4490f617fdfaf359947fbab1..32065cd42adaf9088ff7eb6acfd400c34170b3db 100644 (file)
@@ -3,8 +3,11 @@
 enum npc
 {
    k_npc_none = 0,
-   k_npc_gino,
    k_npc_jc,
+   k_npc_mike,
+   k_npc_fbi,
+   k_npc_human_reserved,
+   k_npc_gino,
    k_npc_max
 };
 
@@ -12,7 +15,7 @@ void _ent_npc_init(void);
 void _ent_npc_render( vg_camera *cam );
 void _ent_npc_goto( v3f pos, i32 uid );
 void _ent_npc_preupdate(void);
-void _ent_npc_speech( enum npc npc_id, const cs_subtitle *subs );
+void _ent_npc_speech( enum npc npc_id, const char *speech_alias );
 void _ent_npc_reset(void);
 void _ent_npc_set_in_cutscene( enum npc npc_id, bool yes );
-entity_call_result ent_npc_call( world_instance *world, ent_call *call );
+entity_event_result ent_npc_event( ent_event *event );
index d33c61a7002e7985182395faf0811dfe967bb937..afc3fccffb1890b56a2322d5e21d8cda9cde8b05 100644 (file)
@@ -9,12 +9,50 @@
 
 static void ent_objective_pass( world_instance *world, ent_objective *objective )
 {
+   objective->flags |= k_ent_objective_passed;
+
+   u32 challenge_index = mdl_entity_id_id( _world.active_challenge_id );
+   ent_challenge *challenge = af_arritm( &world->ent_challenge, challenge_index );
+
+   if( challenge->flags & k_ent_challenge_any_order )
+   {
+      bool winner = 1;
+      u32 next = challenge->first_objective_id;
+      while( mdl_entity_id_type(next) == k_ent_objective )
+      {
+         u32 index = mdl_entity_id_id( next );
+         ent_objective *objective = af_arritm( &world->ent_objective, index );
+         if( !(objective->flags & k_ent_objective_passed) )
+         {
+            winner = 0;
+            break;
+         }
+         next = objective->id_next;
+      }
+
+      if( winner )
+      {
+         vg_audio_lock();
+         vg_audio_oneshot( &audio_challenge[2], 1.0f, 0.0f, 0, 0 );
+         vg_audio_unlock();
+         _ent_challenge_win();
+      }
+      else
+      {
+         vg_info( "pass challenge point\n" );
+         vg_audio_lock();
+         vg_audio_oneshot_3d( &audio_challenge[0], localplayer.rb.co, 30.0f, 1.0f, 0, 0 );
+         vg_audio_unlock();
+      }
+
+      return;
+   }
+
    if( objective->id_next )
    {
       u32 index = mdl_entity_id_id( objective->id_next );
       ent_objective *next = af_arritm( &world->ent_objective, index );
       _world.challenge_target = next;
-      objective->flags |= k_ent_objective_passed;
 
       if( next->filter & k_ent_objective_filter_passthrough )
          ent_objective_pass( world, next );
@@ -39,28 +77,34 @@ static int ent_objective_check_filter( ent_objective *objective )
 {
    if( objective->filter )
    {
-      struct player_skate_state *s = &player_skate.state;
-      enum trick_type trick = s->trick_type;
-
       u32 state = 0x00;
+      if( localplayer.subsystem == k_player_subsystem_skate )
+      {
+         struct player_skate_state *s = &player_skate.state;
+         enum trick_type trick = s->trick_type;
 
-      if( trick == k_trick_type_shuvit ) 
-         state |= k_ent_objective_filter_trick_shuvit;
-      if( trick == k_trick_type_treflip )
-         state |= k_ent_objective_filter_trick_treflip;
-      if( trick == k_trick_type_kickflip )
-         state |= k_ent_objective_filter_trick_kickflip;
-      
-      if( s->flip_rate < -0.0001f ) state |= k_ent_objective_filter_flip_back;
-      if( s->flip_rate >  0.0001f ) state |= k_ent_objective_filter_flip_front;
+         if( trick == k_trick_type_shuvit ) 
+            state |= k_ent_objective_filter_trick_shuvit;
+         if( trick == k_trick_type_treflip )
+            state |= k_ent_objective_filter_trick_treflip;
+         if( trick == k_trick_type_kickflip )
+            state |= k_ent_objective_filter_trick_kickflip;
+         
+         if( s->flip_rate < -0.0001f ) state |= k_ent_objective_filter_flip_back;
+         if( s->flip_rate >  0.0001f ) state |= k_ent_objective_filter_flip_front;
 
-      if( s->activity == k_skate_activity_grind_5050 ||
-          s->activity == k_skate_activity_grind_back50 ||
-          s->activity == k_skate_activity_grind_front50 ) 
-         state |= k_ent_objective_filter_grind_truck_any;
+         if( s->activity == k_skate_activity_grind_5050 ||
+             s->activity == k_skate_activity_grind_back50 ||
+             s->activity == k_skate_activity_grind_front50 ) 
+            state |= k_ent_objective_filter_grind_truck_any;
 
-      if( s->activity == k_skate_activity_grind_boardslide )
-         state |= k_ent_objective_filter_grind_board_any;
+         if( s->activity == k_skate_activity_grind_boardslide )
+            state |= k_ent_objective_filter_grind_board_any;
+      }
+      else if( localplayer.subsystem == k_player_subsystem_glide )
+      {
+         state |= k_ent_objective_filter_glider;
+      }
 
       return ((objective->filter  & state) || !objective->filter) && 
              ((objective->filter2 & state) || !objective->filter2);
@@ -71,70 +115,66 @@ static int ent_objective_check_filter( ent_objective *objective )
    }
 }
 
-entity_call_result ent_objective_call( world_instance *world, ent_call *call )
+entity_event_result ent_objective_event( ent_event *event )
 {
-   u32 index = mdl_entity_id_id( call->id );
-   ent_objective *objective = af_arritm( &world->ent_objective, index );
+   world_instance *world = &_world.main;
+   ent_objective *objective = af_arritm( &world->ent_objective, mdl_entity_id_id( event->recieve_entity_id ) );
 
-   if( call->function == 0 )
+   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "trigger" ) )
    {
       if( (_world.event == k_world_event_challenge) && (_world.challenge_state == k_challenge_state_running) )
       {
          if( objective->flags & (k_ent_objective_hidden|k_ent_objective_passed|k_ent_objective_failed))
-         {
-            return k_entity_call_result_OK;
-         }
+            return k_entity_event_result_OK;
+
+         u32 challenge_index = mdl_entity_id_id( _world.active_challenge_id );
+         ent_challenge *challenge = af_arritm( &world->ent_challenge, challenge_index );
 
-         if( _world.challenge_target )
+         if( challenge->flags & k_ent_challenge_any_order )
          {
-            if( (_world.challenge_target == objective) && ent_objective_check_filter( objective ))
-            {
+            if( ent_objective_check_filter( objective ) )
                ent_objective_pass( world, objective );
-            }
-            else 
+
+            // else do nothing
+         }
+         else
+         {
+            if( _world.challenge_target )
             {
-               vg_audio_lock();
-               vg_audio_oneshot_3d( &audio_challenge[6], localplayer.rb.co, 30.0f, 1.0f, 0, 0 );
-               vg_audio_unlock();
-               vg_error( "challenge failed, filter was not met\n" );
-               objective->flags |= k_ent_objective_failed;
-               _world.challenge_state = k_challenge_state_fail;
-
-               gui_helper_reset( k_gui_helper_mode_black_bars );
-               vg_str str;
-               struct gui_helper *helper;
-               if( (helper = gui_new_helper(input_button_list[k_srbind_reset], &str)) )
+               if( (_world.challenge_target == objective) && ent_objective_check_filter( objective ))
+                  ent_objective_pass( world, objective );
+               else 
                {
-                  vg_strcat( &str, "Retry" );
+                  vg_audio_lock();
+                  vg_audio_oneshot_3d( &audio_challenge[6], localplayer.rb.co, 30.0f, 1.0f, 0, 0 );
+                  vg_audio_unlock();
+                  vg_error( "challenge failed, filter was not met\n" );
+                  objective->flags |= k_ent_objective_failed;
+                  _world.challenge_state = k_challenge_state_fail;
+
+                  gui_helper_reset( k_gui_helper_mode_black_bars );
+                  vg_str str;
+                  struct gui_helper *helper;
+                  if( (helper = gui_new_helper(input_button_list[k_srbind_reset], &str)) )
+                     vg_strcat( &str, "Retry" );
                }
             }
          }
       }
 
-      return k_entity_call_result_OK;
+      return k_entity_event_result_OK;
    }
-   else if( call->function == 2 )
+   else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "hide" ) )
    {
-      objective->flags &= ~k_ent_objective_hidden;
-
-      if( mdl_entity_id_type( objective->id_next ) == k_ent_objective )
+      // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
+      if( event->flags == k_ent_event_data_const_i32 )
       {
-         call->id = objective->id_next;
-         entity_call( world, call );
+         if( event->data.const_i32 ) objective->flags &= ~((u32)k_ent_objective_hidden);
+         else                        objective->flags |=   (u32)k_ent_objective_hidden;
+         return k_entity_event_result_OK;
       }
-      return k_entity_call_result_OK;
-   }
-   else if( call->function == 3 )
-   {
-      objective->flags |=  k_ent_objective_hidden;
-
-      if( mdl_entity_id_type( objective->id_next ) == k_ent_objective )
-      {
-         call->id = objective->id_next;
-         entity_call( world, call );
-      }
-      return k_entity_call_result_OK;
+      else
+         return k_entity_event_result_invalid;
    }
-   else 
-      return k_entity_call_result_unhandled;
+      return k_entity_event_result_unhandled;
 }
index 9d947723e029ec893ad698960b0b6e8937679232..e5e84ace853a6edb2cd2fcd5766c60ab175f3872 100644 (file)
@@ -1,4 +1,4 @@
 #pragma once
 #include "entity.h"
 #include "world.h"
-entity_call_result ent_objective_call( world_instance *world, ent_call *call );
+entity_event_result ent_objective_event( ent_event *event );
index 94ea1ba9c2b30aaa31d266c26ea8ade5504699f3..aa1a906c7872c48ce615a5257ab3270b95b204c0 100644 (file)
@@ -15,15 +15,16 @@ u32 region_spark_colour( u32 flags )
       return 0x00;
 }
 
-entity_call_result ent_region_call( world_instance *world, ent_call *call )
+entity_event_result ent_region_event( ent_event *event )
 {
-   ent_region *region = af_arritm( &world->ent_region, mdl_entity_id_id(call->id) );
+   world_instance *world = &_world.main;
+   ent_region *region = af_arritm( &world->ent_region, mdl_entity_id_id(event->recieve_entity_id) );
    ent_list *challenge_list = NULL;
 
    if( region->v109.id_list != 0 )
       challenge_list = af_arritm( &world->ent_list, mdl_entity_id_id( region->v109.id_list ) );
 
-   if( call->function == 0 ) /* enter */
+   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "set_active" ) )
    {
       gui_location_print_ccmd( 1, (const char *[]){af_str( &world->meta.af, region->pstr_title)} );
       vg_strncpy( af_str( &world->meta.af, region->pstr_title ), 
@@ -56,20 +57,9 @@ entity_call_result ent_region_call( world_instance *world, ent_call *call )
          }
       }
 
-      return k_entity_call_result_OK;
+      return k_entity_event_result_OK;
    }
-   else if( call->function == 1 ) /* leave */
-   {
-      for( u32 i=0; i<af_arrcount(&world->ent_route); i ++ )
-      {
-         ent_route *route = af_arritm( &world->ent_route, i );
-         route->flags |= k_ent_route_flag_out_of_zone;
-      }
-      localplayer.effect_data.spark.colour = 0x00;
-      return k_entity_call_result_OK;
-   }
-   else
-      return k_entity_call_result_unhandled;
+   else return k_entity_event_result_unhandled;
 }
 
 /* 
@@ -120,36 +110,7 @@ void ent_region_re_eval( world_instance *world )
       }
    }
 
-   /* run unlock triggers. v105+ */
-   if( world->meta.version >= 105 )
-   {
-      for( u32 j=0; j<af_arrcount( &world->ent_region ); j ++ )
-      {
-         ent_region *region = af_arritm( &world->ent_region, j );
-         if( region->flags & (k_ent_route_flag_achieve_gold|k_ent_route_flag_achieve_silver) )
-         {
-            if( region->target0[0] )
-            {
-               vg_info( "Trigger region unlock -> %u\n", region->target0[0] );
-
-               struct ent_region_unlock_data data = 
-               {
-                  .world_total = world_total,
-                  .region_total = region->flags
-               };
-
-               ent_call call;
-               call.data = &data;
-               call.id = region->target0[0];
-               call.function = region->target0[1];
-               entity_call( world, &call );
-            }
-         }
-      }
-   }
-
    addon_reg *world_reg = addon_details( _world.main.addon_id );
-
    if( world_reg->flags & ADDON_REG_MTZERO )
    {
       if( world_total & k_ent_route_flag_achieve_gold )
index 886858b64becbc89a7e73fa230ddd96013f2d962..c55edd2af9a5e75aaa14c5057009eb9e0b16d123 100644 (file)
@@ -17,4 +17,4 @@ struct ent_region_unlock_data
 
 u32 region_spark_colour( u32 flags );
 void ent_region_re_eval( world_instance *world );
-entity_call_result ent_region_call( world_instance *world, ent_call *call );
+entity_event_result ent_region_event( ent_event *event );
index e770ad5b416b8235ba2a64a91ef16b3f0d3a03d1..711e71c0e947be5e6cc6c120b81bba2fe03efaac 100644 (file)
@@ -1,25 +1 @@
 #include "ent_relay.h"
-
-entity_call_result ent_relay_call( world_instance *world, ent_call *call )
-{
-   u32 index = mdl_entity_id_id( call->id );
-   ent_relay *relay = af_arritm( &world->ent_relay, index );
-
-   if( call->function == 0 )
-   {
-      for( u32 i=0; i<VG_ARRAY_LEN(relay->targets); i++ )
-      {
-         if( relay->targets[i][0] )
-         {
-            ent_call call;
-            call.data = NULL;
-            call.function = relay->targets[i][1];
-            call.id = relay->targets[i][0];
-            entity_call( world, &call );
-         }
-      }
-      return k_entity_call_result_OK;
-   }
-   else 
-      return k_entity_call_result_unhandled;
-}
index 054570cd6f2e4e3e05ddacb75eaa16602a7ff2a1..9030863ec9bf90f809510c997df807feda6a3700 100644 (file)
@@ -1,3 +1,2 @@
 #pragma once
 #include "entity.h"
-entity_call_result ent_relay_call( world_instance *world, ent_call *call );
index a99ff4187a5cb5a959f73bb0257dfba11ca3bbdd..78b1a61e2e124d789f20670551e1a726373d5e92 100644 (file)
@@ -6,13 +6,13 @@
 
 struct _ent_route _ent_route;
 
-entity_call_result ent_route_call( world_instance *world, ent_call *call )
+entity_event_result ent_route_event( ent_event *event )
 {
-   u32 index = mdl_entity_id_id( call->id );
-   ent_route *route = af_arritm( &world->ent_route, index );
+   world_instance *world = &_world.main;
+   ent_route *route = af_arritm( &world->ent_route, mdl_entity_id_id( event->recieve_entity_id ) );
 
-   if( call->function == 0 )
-   { 
+   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "view" ) )
+   {
       if( world_set_event( k_world_event_route_leaderboard ) )
       {
          menu_close();
@@ -21,15 +21,12 @@ entity_call_result ent_route_call( world_instance *world, ent_call *call )
 
          if( gui_new_helper( input_button_list[k_srbind_mback], &text ) )
             vg_strcat( &text, "Exit" );
-
-         _ent_route.viewing_route_id = call->id;
+         _ent_route.viewing_route_id = event->recieve_entity_id;
          localplayer.immobile = 1;
       }
-
-      return k_entity_call_result_OK;
+      return k_entity_event_result_OK;
    }
-
-   return k_entity_call_result_unhandled;
+   else return k_entity_event_result_unhandled;
 }
 
 void ent_route_preupdate(void)
index efd5022d7795c87245667e68870c7faa2a3bcabb..2c8f08046c3b54d1fe3e021bd5b286d7f975601c 100644 (file)
@@ -13,7 +13,7 @@ struct _ent_route
 }
 extern _ent_route;
 
-entity_call_result ent_route_call( world_instance *world, ent_call *call );
+entity_event_result ent_route_event( ent_event *event );
 void ent_route_preupdate(void);
 void ent_route_leaderboard_ui( ui_context *ctx, ui_rect ref_box, u32 route_index );
 void _ent_route_imgui( ui_context *ctx );
index b63bad4aa8426336f95c89048da3f38086dd449c..2e2a67c4c3ee31337011bbe68b204913de81530f 100644 (file)
@@ -87,32 +87,38 @@ void ent_script_update( world_instance *world )
 
 void ent_script_start( world_instance *world )
 {
+   /* internal start event */
    struct ent_script_event event;
    event.type = k_escript_event_world_start;
    event.info = NULL;
    ent_script_propogate_event( world, &event );
+
+   /* external start event */
+   for( u32 i=0; i<af_arrcount( &world->ent_script ); i ++ )
+      _world_raise_event( mdl_entity_id( k_ent_script, i ), "start" );
 }
 
-entity_call_result ent_script_call( world_instance *world, ent_call *call )
+entity_event_result _ent_script_world_event( ent_event *event )
 {
-   u32 index = mdl_entity_id_id( call->id );
+   world_instance *world = &_world.main;
+   u32 index = mdl_entity_id_id( event->recieve_entity_id );
    ent_script *script = af_arritm( &world->ent_script, index );
 
    if( script->flags & k_ent_script_flag_linked )
    {
-      struct script_event_call info;
-      info.function_id = call->function;
-
-      struct ent_script_event event;
-      ent_script_event_init( &event, world, index );
-      event.type = k_escript_event_call;
-      event.info = &info;
-      _ent_script_table[ script->script_id ].jump( &event );
-      return k_entity_call_result_OK;
+      struct script_event_world_io io_inf;
+      io_inf.event = event;
+
+      struct ent_script_event script_event;
+      ent_script_event_init( &script_event, world, index );
+      script_event.type = k_escript_event_world_event;
+      script_event.info = &io_inf;
+      _ent_script_table[ script->script_id ].jump( &script_event );
+      return k_entity_event_result_OK;
    }
    else
    {
-      vg_error( "Call to script '%u', function '%d', but the script is not linked.\n", index, call->function );
-      return k_entity_call_result_OK;
+      vg_error( "Call to script '%u', but the script is not linked.\n", index );
+      return k_entity_event_result_OK;
    }
 }
index 8fc559ad8ad486fc6b7c8d140e2e26cd91a47c02..3e4457ac95043797addcf762dc10de9abb856c2a 100644 (file)
@@ -6,34 +6,41 @@ struct script_event_allocate
    void *userdata;
 };
 
-struct script_event_call
+struct script_event_world_io
 {
-   i32 function_id;
+   ent_event *event;
 };
 
-struct script_event_nugget_changed
+struct script_event_atom_changed
 {
    const char *alias;
    u64 value;
 };
 
+#if 0
+struct script_event_call
+{
+   i32 function_id;
+};
+
+
 struct script_event_completion_changed
 {
    u32 entity_id;
    u32 completion_flags;
 };
+#endif
 
 typedef struct ent_script_event ent_script_event;
 struct ent_script_event
 {
    enum escript_event
    {
-      k_escript_event_call = 0,
+      k_escript_event_world_event,
       k_escript_event_allocate,
       k_escript_event_update,
       k_escript_event_world_start,
-      k_escript_event_nugget_changed,
-      k_escript_event_completion_changed
+      k_escript_event_atom_changed,
    }
    type;
    void *info;
@@ -55,4 +62,4 @@ void ent_script_propogate_event( world_instance *world, struct ent_script_event
 void ent_script_start( world_instance *world );
 void ent_script_update( world_instance *world );
 void ent_script_alloc( world_instance *world, void *heap );
-entity_call_result ent_script_call( world_instance *world, ent_call *call );
+entity_event_result _ent_script_world_event( ent_event *event );
index fa664feb831fb9c4cf229ea96f501c1ba1413f1e..df786287561f439576951b0c7a32e1423e11c47c 100644 (file)
@@ -288,24 +288,6 @@ void ent_skateshop_update(void)
       else
          vg_fatal_error( "Unknown store (%u)\n", shop->type );
    }
-   else
-   {
-      if( button_down( k_srbind_use ) )
-      {
-         menu_close();
-         ent_skateshop *shop = _skateshop.current_shop;
-         if( shop->type == k_skateshop_type_boardshop )
-         {
-            skateshop_update_viewpage();
-            skateshop_scan( k_addon_type_board );
-         }
-
-         gui_helper_reset( k_gui_helper_mode_clear );
-         ent_skateshop_helpers_pickable( "Pick" );
-         _skateshop.open = 1;
-         skateshop_playermod( 1 );
-      }
-   }
 }
 
 static void skateshop_render_boardshop( ent_skateshop *shop, vg_camera *cam )
@@ -520,38 +502,32 @@ void ent_skateshop_render( vg_camera *cam )
    }
 }
 
-entity_call_result ent_skateshop_call( world_instance *world, ent_call *call )
+entity_event_result ent_skateshop_event( ent_event *event )
 {
-   u32 index = mdl_entity_id_id( call->id );
-   ent_skateshop *shop = af_arritm( &world->ent_skateshop, index );
+   world_instance *world = &_world.main;
+   ent_skateshop *shop = af_arritm( &world->ent_skateshop, mdl_entity_id_id( event->recieve_entity_id ) );
 
-   if( call->function == 0 ) /* view() */
+   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "open" ) )
    {
-      if( localplayer.subsystem == k_player_subsystem_walk )
+      if( world_set_event( k_world_event_shop ) )
       {
-         if( world_set_event( k_world_event_shop ) )
+         menu_close();
+         _skateshop.current_shop = shop;
+         if( shop->type == k_skateshop_type_boardshop )
          {
-            _skateshop.current_shop = shop;
-            gui_helper_reset( k_gui_helper_mode_black_bars );
-
-            vg_str text;
-            if( gui_new_helper( input_button_list[k_srbind_use], &text ))
-               vg_strcat( &text, "Open Shop" );
+            skateshop_update_viewpage();
+            skateshop_scan( k_addon_type_board );
          }
-      }
-      return k_entity_call_result_OK;
-   }
-   else if( call->function == -1 ) /* unview() */
-   {
-      if( world_clear_event( k_world_event_shop ) )
-      {
-         _skateshop.current_shop = NULL;
+
          gui_helper_reset( k_gui_helper_mode_clear );
+         ent_skateshop_helpers_pickable( "Pick" );
+         _skateshop.open = 1;
+         skateshop_playermod( 1 );
       }
-      return k_entity_call_result_OK;
+
+      return k_entity_event_result_OK;
    }
-   else 
-      return k_entity_call_result_unhandled;
+   else return k_entity_event_result_unhandled;
 }
 
 void ent_skateshop_gui( ui_context *ctx )
index 182bcd6177067644845f8064ea47183d4c2dccb3..b913ed18b7a94a045ab2870c5668b15ff0da4733 100644 (file)
@@ -46,5 +46,5 @@ void ent_skateshop_render( vg_camera *cam );
 
 void skateshop_autostart_loading(void);
 void skateshop_world_preupdate(void);
-entity_call_result ent_skateshop_call( world_instance *world, ent_call *call );
+entity_event_result ent_skateshop_event( ent_event *event );
 void skateshop_world_preview_preupdate(void);
index 7a644229228cad90b34006c5b7a72ebf41ffd64b..200450292b60a77bad2e8caa3e7a83009d6bc28b 100644 (file)
 
 #include <string.h>
 
-/* 
- * TODO: Does this really need to take a world parameter, now that we're only using one world?
- */
-void entity_call( world_instance *world, ent_call *call )
-{
-   u32 type = mdl_entity_id_type( call->id ),
-       index = mdl_entity_id_id( call->id );
-
-   fn_entity_call_handler table[] = {
-      [k_ent_volume]    = ent_volume_call,
-      [k_ent_audio]     = ent_audio_call,
-      [k_ent_skateshop] = ent_skateshop_call,
-      [k_ent_objective] = ent_objective_call,
-      [k_ent_ccmd]      = ent_ccmd_call,
-      [k_ent_gate]      = ent_gate_call,
-      [k_ent_relay]     = ent_relay_call,
-      [k_ent_challenge] = ent_challenge_call,
-      [k_ent_route]     = ent_route_call,
-      [k_ent_region]    = ent_region_call,
-      [k_ent_glider]    = ent_glider_call,
-      [k_ent_water]     = ent_water_call,
-      [k_ent_script]    = ent_script_call,
-      [k_ent_npc]       = ent_npc_call,
-   };
-
-   if( type >= VG_ARRAY_LEN(table) ){
-      vg_error( "call to entity type: %u is out of range\n", type );
-      return;
-   }
-
-   fn_entity_call_handler fn = table[ type ];
-
-   if( !fn )
-   {
-      vg_error( "Entity type %u does not have a call handler, but was called anyway\n", type );
-      return;
-   }
-
-   enum entity_call_result res = fn( world, call );
-   if( res == k_entity_call_result_unhandled )
-      vg_warn( "Call to entity %u#%u was unhandled.\n", type, index );
-}
-
-ent_marker *ent_find_marker( mdl_context *mdl, array_file_ptr *arr, 
-                             const char *alias )
-{
-   for( u32 i=0; i<af_arrcount(arr); i++ )
-   {
-      ent_marker *marker = af_arritm( arr, i );
-
-      if( !strcmp( af_str( &mdl->af, marker->pstr_alias ), alias ) )
-      {
-         return marker;
-      }
-   }
-
-   return NULL;
-}
-
index a50c1375ac5783400d0b6f36b6ea494c0bab4a08..40aecb430d03b3f1c203adf4c251855c5eba976d 100644 (file)
@@ -62,7 +62,7 @@ enum entity_alias{
    k_ent_ccmd        = 17,
    k_ent_objective   = 18,
    k_ent_challenge   = 19,
-   k_ent_relay       = 20,
+   k_ent_deleted0    = 20, //k_ent_relay       = 20,
    k_ent_cubemap     = 21,
    k_ent_miniworld   = 22,
    k_ent_prop        = 23,
@@ -71,7 +71,7 @@ enum entity_alias{
    k_ent_glider      = 26,
    k_ent_npc         = 27,
    k_ent_armature    = 28,
-   k_ent_script      = 29,
+   k_ent_script      = 29, 
    k_ent_max
 };
 
@@ -97,7 +97,7 @@ const char *_entity_alias_str[] =
    [k_ent_ccmd] = "ent_ccmd",
    [k_ent_objective] = "ent_objective",
    [k_ent_challenge] = "ent_challenge",
-   [k_ent_relay] = "ent_relay",
+   //[k_ent_relay] = "ent_relay",
    [k_ent_cubemap] = "ent_cubemap",
    [k_ent_miniworld] = "ent_miniworld",
    [k_ent_prop] = "ent_prop",
@@ -108,15 +108,6 @@ const char *_entity_alias_str[] =
    [k_ent_script] = "ent_script"
 };
 
-typedef struct ent_call ent_call;
-typedef enum entity_call_result entity_call_result;
-enum entity_call_result 
-{
-   k_entity_call_result_OK,
-   k_entity_call_result_unhandled,
-   k_entity_call_result_invalid
-};
-
 static inline u32 mdl_entity_id_type( u32 entity_id )
 {
    return (entity_id & 0x0fff0000) >> 16;
@@ -132,13 +123,6 @@ static inline u32 mdl_entity_id( u32 type, u32 index )
    return (type & 0xfffff)<<16 | (index & 0xfffff);
 }
 
-enum entity_function
-{
-   k_ent_function_trigger,
-   k_ent_function_particle_spawn,
-   k_ent_function_trigger_leave
-};
-
 enum ent_spawn_flag
 {
    k_ent_spawn_flag_locked = 0x1,
@@ -148,26 +132,27 @@ enum ent_spawn_flag
    k_ent_spawn_flag_group_4 = 0x80
 };
 
-struct ent_spawn{
+struct ent_spawn
+{
    mdl_transform transform;
    u32 pstr_name;
    u32 flags;
 };
 
-enum light_type{
+enum light_type
+{
    k_light_type_point = 0,
    k_light_type_spot = 1
 };
 
-struct ent_light{
+struct ent_light
+{
    mdl_transform transform;
    u32 daytime,
        type;
-
    v4f colour;
    float angle,
          range;
-
    m4x3f inverse_world;
    v2f angle_sin_cos;
 };
@@ -197,7 +182,7 @@ struct ent_list
 
 struct file_entity_ref
 {
-   u32 entity_id;
+   u32 entity_id, pstr_alias;
 };
 
 /* v102+ */
@@ -215,7 +200,8 @@ enum ent_gate_flag
    k_ent_gate_passive     = 0x80
 };
 
-struct ent_gate{
+struct ent_gate
+{
    u32 flags,
        target, 
        key;
@@ -273,11 +259,14 @@ enum ent_route_flag {
    k_ent_route_flag_achieve_gold   = 0x2,
 
    k_ent_route_flag_out_of_zone    = 0x10,
-   k_ent_region_flag_hasname       = 0x20
+   k_ent_region_flag_hasname       = 0x20,
+   k_ent_route_flag_target         = 0x40
 };
 
-struct ent_route{
-   union{
+struct ent_route
+{
+   union
+   {
       mdl_transform transform;
       u32 official_track_id;   /* TODO: remove this */
    }
@@ -304,11 +293,11 @@ struct ent_route{
    u32 flags;
    f64 best_laptime;
    f32 ui_stopper, ui_residual;
-
    ui_px ui_first_block_width, ui_residual_block_w;
 };
 
-struct ent_water{
+struct ent_water
+{
    mdl_transform transform;
    float max_dist;
    u32 reserved0, reserved1;
@@ -323,17 +312,19 @@ struct ent_audio_clip{
    float probability;
 };
 
-struct volume_particles{
+struct volume_particles
+{
    u32 blank, blank2;
 };
 
-struct volume_trigger{
-   i32 event, event_leave;
+struct volume_trigger
+{
+   i32 blank, blank2;
 };
 
 struct volume_interact
 {
-   i32 activate_event;
+   i32 blank;
    u32 pstr_text;
 };
 
@@ -349,10 +340,17 @@ enum ent_volume_flag {
 struct ent_volume
 {
    mdl_transform transform;
-   m4x3f to_world, to_local;
+   m4x3f to_world;
+
+   union
+   {
+      m4x3f to_local;
+      v3f   particle_co;
+   };
+
    u32 flags;
 
-   u32 target;
+   u32 deleted0;
    union
    {
       volume_trigger trigger;
@@ -361,7 +359,8 @@ struct ent_volume
    };
 };
 
-struct ent_audio{
+struct ent_audio
+{
    mdl_transform transform;
    u32 flags,
        clip_start,
@@ -394,32 +393,38 @@ enum skateshop_type{
    k_skateshop_type_server = 4
 };
 
-struct ent_skateshop{
+struct ent_skateshop
+{
    mdl_transform transform;
    u32 type, id_camera;
 
-   union{
-      struct{
+   union
+   {
+      struct
+      {
          u32 id_display,
              id_info,
              id_rack;
       }
       boards;
 
-      struct{
+      struct
+      {
          u32 id_display,
              id_info,
              id_rack;
       }
       character;
 
-      struct{
+      struct
+      {
          u32 id_display,
              id_info;
       }
       worlds;
 
-      struct{
+      struct
+      {
          u32 id_lever;
       }
       server;
@@ -557,10 +562,8 @@ struct ent_worldinfo
    f32 wind_scale;
 };
 
-ent_marker *ent_find_marker( mdl_context *mdl, array_file_ptr *arr, 
-                             const char *alias );
-
-enum channel_behaviour{
+enum channel_behaviour
+{
    k_channel_behaviour_unlimited = 0,
    k_channel_behaviour_discard_if_full = 1,
    k_channel_behaviour_crossfade_if_full = 2
@@ -633,7 +636,8 @@ enum ent_objective_filter{
       k_ent_objective_filter_grind_truck_any|
       k_ent_objective_filter_grind_board_any,
    k_ent_objective_filter_footplant       = 0x00000080,
-   k_ent_objective_filter_passthrough     = 0x00000100
+   k_ent_objective_filter_passthrough     = 0x00000100,
+   k_ent_objective_filter_glider          = 0x00000200
 };
 
 enum ent_objective_flag 
@@ -662,6 +666,8 @@ enum ent_challenge_flag
    k_ent_challenge_timelimit = 0x1,
    //k_ent_challenge_is_story  = 0x2,
    k_ent_challenge_locked    = 0x4,
+   k_ent_challenge_any_order = 0x8,
+   k_ent_challenge_target    = 0x10
 };
 
 struct ent_challenge
@@ -670,11 +676,10 @@ struct ent_challenge
    u32 pstr_alias,
        flags;
 
-   u32 on_activate_id;
-   u32 on_activate_event;
-
-   u32 on_complete_id;
-   i32 on_complete_event;
+   u32 deleted0;//on_activate_id;
+   u32 deleted1;//on_activate_event;
+   u32 deleted2;//on_complete_id;
+   i32 deleted3;//on_complete_event;
 
    u32 first_objective_id;
    u32 camera_id;
@@ -683,24 +688,13 @@ struct ent_challenge
    u32 reset_spawn_id;
 };
 
-struct ent_relay {
-   u32 targets[4][2];
-   i32 targets_events[4];
-};
-
-struct ent_cubemap {
+struct ent_cubemap 
+{
    v3f co;
    u32 resolution, live, texture_id, 
        framebuffer_id, renderbuffer_id, placeholder[2];
 };
 
-struct ent_miniworld {
-   mdl_transform transform;
-   u32 pstr_world;
-   u32 camera;
-   u32 proxy;
-};
-
 enum prop_flag
 {
    k_prop_flag_hidden = 0x1,
@@ -709,7 +703,8 @@ enum prop_flag
    k_prop_flag_spinning_fast = 0x8,
 };
 
-struct ent_prop {
+struct ent_prop 
+{
    mdl_transform transform;
    u32 submesh_start, submesh_count, flags, pstr_alias;
 };
@@ -726,10 +721,11 @@ struct ent_region
    };
 
    /* 105+ */
-   u32 target0[2];
+   u32 deleted01[2];
 };
 
-struct ent_glider {
+struct ent_glider 
+{
    mdl_transform transform;
    u32 flags;
    f32 cooldown;
@@ -741,13 +737,43 @@ struct ent_npc
    u32 pstr_id, pstr_context_id;
 };
 
-#include "world.h"
+typedef enum entity_event_result entity_event_result;
+enum entity_event_result 
+{
+   k_entity_event_result_OK,
+   k_entity_event_result_unhandled,
+   k_entity_event_result_invalid
+};
 
-struct ent_call{
-   u32 id;
-   i32 function;
-   void *data;
+enum ent_event_flags
+{
+   k_ent_event_data_const_i32 = 0x1,
+   k_ent_event_data_const_f32 = 0x2,
+   k_ent_event_data_const_entity_id = 0x4,
+   k_ent_event_data_const_string = 0x8,
+   k_ent_event_data_data_alias = 0x10,
+   k_ent_event_data_v3f = 0x20
 };
 
-typedef enum entity_call_result (*fn_entity_call_handler)( world_instance *, ent_call *);
-void entity_call( world_instance *world, ent_call *call );
+typedef struct ent_event ent_event;
+struct ent_event
+{
+   u32 pstr_source_event,
+       pstr_recieve_event,
+       source_entity_id,
+       recieve_entity_id,
+       flags;
+
+   f32 delay;
+   u32 unused0;
+
+   union
+   {
+      i32 const_i32;
+      f32 const_f32;
+      u32 const_entity_id;
+      u32 const_pstr;
+      u32 pstr_data_alias;
+   }
+   data;
+};
index 7750eb8ebc4e43972ab14c442a10e15dc49ba3f1..67e1db742a4323cbec8d941e204e220b21bd16bd 100644 (file)
@@ -387,7 +387,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( "unlock_venus" );
+      world_map.selected_superworld_locked = !_skaterift_atom_status( "unlock_venus" );
    }
 
    if( world_map.selected_superworld_locked )
@@ -428,11 +428,11 @@ void menu_update_world_list(void)
          addon_reg *reg = addon_details( addon_id );
          bool unlocked = 1;
          if( reg->flags & ADDON_REG_MTZERO )
-            unlocked = _skaterift_script_nugget_status( "unlock_mtzero" )?1:0;
+            unlocked = _skaterift_atom_status( "unlock_mtzero" )?1:0;
          if( reg->flags & ADDON_REG_CITY )
-            unlocked = _skaterift_script_nugget_status( "unlock_city" )?1:0;
+            unlocked = _skaterift_atom_status( "unlock_city" )?1:0;
          if( reg->flags & ADDON_REG_VALLEY )
-            unlocked = _skaterift_script_nugget_status( "unlock_valley" )?1:0;
+            unlocked = _skaterift_atom_status( "unlock_valley" )?1:0;
 
          menu.world_list_entries[ menu.world_list_display_count ] = unlocked? addon_id: 0;
 
@@ -836,6 +836,7 @@ void menu_gui( ui_context *ctx )
             {
                if( world_clear_event( k_world_event_challenge ) )
                {
+                  _ent_challenge_clear( af_arritm( &_world.main.ent_challenge, mdl_entity_id_id( _world.active_challenge_id ) ) );
                   gui_helper_reset( k_gui_helper_mode_clear );
                   _world.challenge_state = k_challenge_state_none;
                   _world.active_challenge_id = 0;
@@ -984,6 +985,7 @@ n1:
       if( menu_button( ctx, a, R == 0, 1, "Skip" ) )
       {
          _cutscene.fadeout = 1;
+         _cutscene.skipped = 1;
          _cutscene.fadeout_start = _cutscene.time;
          _cutscene.meta.info.end_frame = (f32)_cutscene.meta.info.framerate * (_cutscene.time + 0.25f);
          menu_close();
index 2867488c6e53983d37a4de8be916cbc0fc30901f..8aacd47b1704a6434116088fa1c61fc034ce96f7 100644 (file)
@@ -56,10 +56,9 @@ void _cutscene_unload(void)
    _cutscene.state = k_cutscene_state_unloading;
    _cutscene.player_binding = NULL;
    _cutscene.subtitle = NULL;
-   _cutscene.subtitle_length_warning = 0;
-   _cutscene.subtitle_list = NULL;
-   _cutscene.subtitle_index = 0;
+   _cutscene.raiser_entity = 0;
    _cutscene.fadeout = 0;
+   _cutscene.skipped = 0;
    _cutscene.fadeout_start = 0.0f;
 }
 
@@ -111,18 +110,18 @@ NOT_IMPLEMENTED:
    vg_fatal_exit();
 }
 
-static void _cutscene_get_strip_asoc( ms_strip *strip, 
-                                      struct cs_asoc *out_asoc )
+static void _cutscene_get_strip_asoc( ms_strip *strip, struct cs_asoc *out_asoc )
 {
-   if( strip->instance_id == 0xffffffff )
+   VG_ASSERT( strip->mode & k_ms_strip_mode_animation );
+   if( strip->strip.instance_id == 0xffffffff )
    {
       out_asoc->orig_data = NULL;// &_cutscene.meta;
-      out_asoc->entity_type = mdl_entity_id_type( strip->object_id );
-      out_asoc->entity_index = mdl_entity_id_id( strip->object_id );
+      out_asoc->entity_type = mdl_entity_id_type( strip->strip.object_id );
+      out_asoc->entity_index = mdl_entity_id_id( strip->strip.object_id );
       out_asoc->override = NULL;
    }
    else
-      _cutscene_override_asoc( strip->instance_id, strip->object_id, out_asoc );
+      _cutscene_override_asoc( strip->strip.instance_id, strip->strip.object_id, out_asoc );
 }
 
 static void sync_cutscene_loaded( void *userdata )
@@ -284,16 +283,20 @@ static void cutscene_load_thread( vg_async_task *task )
    vg_async_call( &vg.main_tasks, sync_cutscene_loaded, NULL );
 }
 
-void _cutscene_load_and_play( const char *path, const cs_subtitle *subtitles, bool freeze_player )
+void _cutscene_load_and_play( const char *path, bool freeze_player, u32 raiser_entity )
 {
-   VG_ASSERT( _cutscene.state == k_cutscene_state_none );
+   if( _cutscene.state != k_cutscene_state_none )
+   {
+      vg_error( "Tried to play cutscene '%s' while already playing one.\n", path );
+      return;
+   }
+
+   _cutscene.raiser_entity = raiser_entity;
 
    for( u32 i=0; i<k_npc_max; i ++ )
       _ent_npc_set_in_cutscene( i, 0 );
 
    _cutscene.state = k_cutscene_state_loading;
-   _cutscene.subtitle_list = subtitles;
-   _cutscene.subtitle_index = 0;
    _cutscene.time = 0.0f;
    _cutscene.strip = 0;
    _cutscene.active_samplers = 0;
@@ -322,6 +325,7 @@ void cutscene_render_instance( struct cs_instance *ins, world_instance *world, v
    shader_model_character_view_uCamera( cam->transform[3] );
    shader_model_character_view_uPv( cam->mtx.pv );
    shader_model_character_view_uDepthMode( 0 );
+   shader_model_character_view_uShadeless( 0 );
 
    WORLD_BIND_LIGHT_BUFFERS_UB0_TEX234( world, model_character_view );
 
@@ -330,6 +334,7 @@ void cutscene_render_instance( struct cs_instance *ins, world_instance *world, v
 
    u32 armature_id = 0x00;
    u32 material_id = 0x00;
+   bool using_additive = 0;
 
    for( u32 i=0; i<mdl->mesh_count; i ++ )
    {
@@ -342,12 +347,9 @@ void cutscene_render_instance( struct cs_instance *ins, world_instance *world, v
          u32 sk_index = mdl_entity_id_id( armature_id );
 
          struct cs_skeleton *skele = &ref->skeletons[ sk_index ];
-
          m4x3f *skinning_data = ins->skinning_data + skele->skinning_offset;
-         glUniformMatrix4x3fv( _uniform_model_character_view_uTransforms,
-               skele->sk.bone_count,
-               0,
-               (const GLfloat *)skinning_data );
+         glUniformMatrix4x3fv( _uniform_model_character_view_uTransforms, skele->sk.bone_count, 0,
+                               (const GLfloat *)skinning_data );
       }
 
       for( u32 j=0; j<mesh->submesh_count; j ++ )
@@ -365,11 +367,40 @@ void cutscene_render_instance( struct cs_instance *ins, world_instance *world, v
 
             mdl_texture *tex = &mdl->textures[ props->tex_diffuse-1 ];
             glBindTexture( GL_TEXTURE_2D, tex->glname );
+
+            if( props->render_flags & k_material_render_additive )
+            {
+               using_additive = 1;
+               glDepthMask(GL_FALSE);
+               glEnable(GL_BLEND);
+               glBlendFunc(GL_ONE, GL_ONE);
+               glBlendEquation(GL_FUNC_ADD);
+               glDisable( GL_CULL_FACE );
+               shader_model_character_view_uShadeless( 1 );
+            }
+            else
+            {
+               if( using_additive )
+               {
+                  using_additive = 0;
+                  glDepthMask(GL_TRUE);
+                  glDisable(GL_BLEND);
+                  glEnable( GL_CULL_FACE );
+                  shader_model_character_view_uShadeless( 0 );
+               }
+            }
          }
 
          mdl_draw_submesh( sm );
       }
    }
+
+   if( using_additive )
+   {
+      shader_model_character_view_uShadeless( 0 );
+      glDepthMask(GL_TRUE);
+      glDisable(GL_BLEND);
+   }
 }
 
 #define CS_LOCATION 0
@@ -382,11 +413,13 @@ struct cs_link_info
    u32 semantic_type;
 };
 
-static bool link_internal_datapath( struct cs_asoc *asoc, const char *datapath,
-      struct cs_link_info *out_link )
+static bool link_internal_datapath( struct cs_asoc *asoc, const char *datapath, struct cs_link_info *out_link )
 {
-   VG_ASSERT( asoc->entity_type == k_ent_camera );
-
+   if( asoc->entity_type != k_ent_camera )
+   {
+      vg_warn( "Failed link %d#%d:'%s'\n", asoc->entity_type, asoc->entity_index, datapath );
+      VG_ASSERT( 0 );
+   }
    ent_camera *cam = af_arritm( &_cutscene.meta.cameras, asoc->entity_index );
 
    struct
@@ -468,7 +501,7 @@ void cutscene_update( f32 delta )
       _cutscene.state = k_cutscene_state_none;
       _cutscene.marker_this_frame = NULL;
       _cutscene.subtitle = NULL;
-      _cutscene.subtitle_length_warning = 0;
+      _cutscene.raiser_entity = 0;
       return;
    }
 
@@ -486,7 +519,7 @@ void cutscene_update( f32 delta )
    {
       struct cs_sampler *si = &_cutscene.samplers[i];
 
-      if( frame > (si->strip->offset + si->strip->length) )
+      if( frame > (si->strip->offset + si->strip->strip.length) )
          move = 1;
       else
       {
@@ -509,78 +542,35 @@ void cutscene_update( f32 delta )
       if( frame < strip->offset )
          break;
 
-      if( frame > strip->offset + strip->length )
-      {
-         vg_warn( "Skipping?\n" );
-         _cutscene.strip ++;
-         continue;
-      }
-
-      if( strip->data_mode == 2 )
+      if( strip->mode & k_ms_strip_mode_animation )
       {
-         if( strip->object_id )
+         if( frame > strip->offset + strip->strip.length )
          {
-            struct cs_asoc asoc;
-            _cutscene_get_strip_asoc( strip, &asoc );
-
-            VG_ASSERT( asoc.entity_type == k_ent_camera );
-            ent_camera *cam = af_arritm( &_cutscene.meta.cameras, asoc.entity_index );
-
-            _cutscene.active_camera = cam;
+            vg_warn( "Skipping?\n" );
+            _cutscene.strip ++;
+            continue;
          }
-         //else
-         //   _cutscene.active_camera = NULL;
 
-         const char *marker = af_str( &_cutscene.meta.af, strip->pstr_name );
-         vg_info( "Cutscene marker: %s\n", marker );
-
-         bool absorbed = 0;
-
-         if( vg_str_eq( marker, "$fadeout" ) )
-         {
-            _cutscene.fadeout = 1;
-            _cutscene.fadeout_start = _cutscene.time;
-            absorbed = 1;
-         }
-         else if( _cutscene.subtitle_list )
+         if( _cutscene.skipped == 2 )
          {
-            const cs_subtitle *next = &_cutscene.subtitle_list[ _cutscene.subtitle_index ];
-
-            if( next->key )
-            {
-               if( vg_str_eq( marker, next->key ) )
-               {
-                  _cutscene.subtitle = next->value;
-                  _cutscene.subtitle_length_warning = 0;
-                  _cutscene.subtitle_index ++;
-                  absorbed = 1;
-               }
-               else if( vg_str_eq( marker, "$clear_subtitles" ) )
-               {
-                  _cutscene.subtitle = NULL;
-                  _cutscene.subtitle_length_warning = 0;
-                  absorbed = 1;
-               }
-            }
+            _cutscene.strip ++;
+            continue;
          }
 
-         if( !absorbed )
-            _cutscene.marker_this_frame = marker;
-      }
-      else
-      {
-         if( strip->instance_id == 0xffffffff )
+         if( strip->strip.instance_id == 0xffffffff )
          {
-            vg_info( "+ Strip: '%s' entity: %u\n", af_str( &_cutscene.meta.af, strip->pstr_name ), strip->object_id );
+            const char *strip_name = af_str( &_cutscene.meta.af, strip->strip.pstr_name );
+            vg_info( "+ Strip: '%s' entity: %u\n", strip_name, strip->strip.object_id );
+
             /* internal link */
             struct cs_asoc asoc;
             _cutscene_get_strip_asoc( strip, &asoc );
 
-            if( strip->data_mode == 1 )
+            if( strip->mode == k_ms_strip_mode_curves )
             {
-               for( u32 j=0; j<strip->data_count; j ++ )
+               for( u32 j=0; j<strip->strip.count; j ++ )
                {
-                  ms_track *track = af_arritm( &_cutscene.meta.tracks, strip->data_start + j );
+                  ms_track *track = af_arritm( &_cutscene.meta.tracks, strip->strip.start + j );
                   const char *datapath = af_str( &_cutscene.meta.af, track->pstr_datapath );
                   
                   struct cs_link_info link;
@@ -604,17 +594,12 @@ void cutscene_update( f32 delta )
          else
          {
             /* external link */
-            struct cs_instance *ins = &_cutscene.instances[ strip->instance_id ];
-
+            struct cs_instance *ins = &_cutscene.instances[ strip->strip.instance_id ];
             struct cs_asoc asoc;
             _cutscene_get_strip_asoc( strip, &asoc );
             VG_ASSERT( asoc.entity_type == 28 );
 
-            if( strip->data_mode == 1 )
-            {
-               VG_ASSERT(0);
-            }
-            else
+            if( strip->mode == k_ms_strip_mode_keyframes )
             {
                VG_ASSERT( _cutscene.active_samplers < VG_ARRAY_LEN(_cutscene.samplers) );
 
@@ -627,6 +612,40 @@ void cutscene_update( f32 delta )
                samp->skeleton.ref_sk = &skele->sk;
                samp->override = asoc.override;
             }
+            else
+            {
+               VG_ASSERT(0);
+            }
+         }
+      }
+      else
+      {
+         if( strip->mode == k_ms_strip_mode_camera )
+         {
+            u32 type = mdl_entity_id_type( strip->camera.entity_id ),
+                index = mdl_entity_id_id( strip->camera.entity_id );
+            VG_ASSERT( type == k_ent_camera );
+            ent_camera *cam = af_arritm( &_cutscene.meta.cameras, index );
+            _cutscene.active_camera = cam;
+         }
+
+         if( strip->mode == k_ms_strip_mode_fadeout )
+         {
+            _cutscene.fadeout = 1;
+            _cutscene.fadeout_start = _cutscene.time;
+         }
+
+         if( strip->mode == k_ms_strip_mode_subtitle )
+         {
+            // FIXME: COLOURS
+            _cutscene.subtitle = af_str( &_cutscene.meta.af, strip->subtitle.pstr_en );
+         }
+
+         if( strip->mode == k_ms_strip_mode_event )
+         {
+            const char *str = af_str( &_cutscene.meta.af, strip->event.pstr_string );
+            vg_info( "cutscene event: %s\n", str );
+            _world_raise_event( _cutscene.raiser_entity, str );
          }
       }
 
@@ -634,17 +653,17 @@ void cutscene_update( f32 delta )
    }
 
    /* sample da samplers */
-   for( u32 i=0; i<_cutscene.active_samplers; i ++ )
+   for( u32 i=0; i<_cutscene.active_samplers && (_cutscene.skipped != 2); i ++ )
    {
       struct cs_sampler *samp = &_cutscene.samplers[ i ];
 
-      if( samp->strip->data_mode == 0 )
+      if( samp->strip->mode == k_ms_strip_mode_keyframes )
       {
          struct skeleton_anim temp_anim = 
          {
             .strip = samp->strip,
             .framerate = _cutscene.meta.info.framerate,
-            .keyframes_base = af_arritm( &_cutscene.meta.keyframes, samp->strip->data_start )
+            .keyframes_base = af_arritm( &_cutscene.meta.keyframes, samp->strip->strip.start )
          };
 
          f32 t  = _cutscene.time;
@@ -673,7 +692,7 @@ void cutscene_update( f32 delta )
       else
       {
          f32 scene_t = _cutscene.time * _cutscene.meta.info.framerate,
-             t = (f32)(scene_t - samp->strip->offset) + samp->strip->timing_offset;
+             t = (f32)(scene_t - samp->strip->offset) + samp->strip->strip.timing_offset;
 
          ms_curve_keyframe *kl = af_arritm( &_cutscene.meta.curves, 
                   samp->curves.track->keyframe_start + samp->curves.keyframe ),
@@ -722,6 +741,14 @@ void cutscene_update( f32 delta )
 
    if( scene_t >= end_t )
    {
+      if( _cutscene.strip != af_arrcount(&_cutscene.meta.strips) )
+      {
+         _cutscene.time = 9999999.9f;
+         _cutscene.skipped = 2; /* signal we can ignore animation strips, just want events for correctness */
+         return;
+      }
+      _world_raise_event( _cutscene.raiser_entity, "end" );
+
       if( _cutscene.freeze_player )
          localplayer.immobile = 0;
 
@@ -784,7 +811,6 @@ void _cutscene_gui( ui_context *ctx )
       ctx->font = &vgf_default_small;
       ctx->kern[1] = 16;
       ui_px scale = 2;
-
       ui_rect box = { 0,0, 1000, 80*2 };
       ui_rect_center( (ui_rect){0,0,vg.window_x,vg.window_y}, box );
       box[1] = vg.window_y - (box[3] + 8);
@@ -825,19 +851,7 @@ void _cutscene_gui( ui_context *ctx )
 
             ui_fill( ctx, background_rect, ui_opacity( GUI_COL_DARK, 0.75f ) );
             y += (ctx->font->sy)*scale + 16;
-
-            if( !_cutscene.subtitle_length_warning && (length > 50) )
-            {
-               vg_warn( "Subtitle text too long; '%s'\nLine limit 50chs, line was: %u\n", _cutscene.subtitle, length );
-               _cutscene.subtitle_length_warning = 1;
-            }
             length = 0;
-
-            if( !_cutscene.subtitle_length_warning && (lines == 2) && (c != '\0') )
-            {
-               vg_warn( "Subtitle contains more than 2 lines; '%s'\n", _cutscene.subtitle );
-               _cutscene.subtitle_length_warning = 1;
-            }
             lines ++;
          }
          
@@ -899,7 +913,7 @@ static void cb_cutscene_view( ui_context *ctx, ui_rect rect, struct vg_magi_pane
       {
          ms_strip *strip = af_arritm(&_cutscene.meta.strips, i );
 
-         if( strip->data_mode == 2 )
+         if( !(strip->mode & k_ms_strip_mode_animation) )
          {
             ui_rect box = { root[0]+strip->offset, root[1], 1, panel_r[3]-16 };
             ui_fill( ctx, box, 0xff00ff00 );
@@ -909,7 +923,14 @@ static void cb_cutscene_view( ui_context *ctx, ui_rect rect, struct vg_magi_pane
             box[3] = 16;
 
             if( ui_clip( panel_r, box, box ) )
-               ui_text( ctx, box, af_str( &_cutscene.meta.af, strip->pstr_name ), 1, k_ui_align_middle_left, 0 );
+            {
+               if( strip->mode == k_ms_strip_mode_camera )
+                  ui_text( ctx, box, "Camera", 1, k_ui_align_middle_left, 0 );
+               if( strip->mode == k_ms_strip_mode_subtitle )
+                  ui_text( ctx, box, "\"", 1, k_ui_align_middle_left, 0 );
+               if( strip->mode == k_ms_strip_mode_fadeout )
+                  ui_text( ctx, box, "\\", 1, k_ui_align_middle_left, 0 );
+            }
             continue;
          }
          
@@ -917,7 +938,7 @@ static void cb_cutscene_view( ui_context *ctx, ui_rect rect, struct vg_magi_pane
          for( u32 k=0; k<VG_ARRAY_LEN(usage); k ++ )
          {
             if( usage[k] )
-               if( usage[k]->offset + usage[k]->length < strip->offset )
+               if( usage[k]->offset + usage[k]->strip.length < strip->offset )
                   usage[k] = NULL;
 
             if( !usage[k] )
@@ -928,16 +949,15 @@ static void cb_cutscene_view( ui_context *ctx, ui_rect rect, struct vg_magi_pane
             }
          }
 
-         ui_rect box = { strip->offset, layer*32, strip->length, 30 };
+         ui_rect box = { strip->offset, layer*32, strip->strip.length, 30 };
          box[0] += root[0];
          box[1] += root[1];
 
          if( ui_clip( panel_r, box, box ) )
          {
-            u32 colour = af_str_hash( &_cutscene.meta.af, strip->pstr_name );
-
+            u32 colour = af_str_hash( &_cutscene.meta.af, strip->strip.pstr_name );
             ui_fill( ctx, box, colour | 0xff000000 );
-            ui_text( ctx, box, af_str( &_cutscene.meta.af, strip->pstr_name ), 1, k_ui_align_middle_center, 0 );
+            ui_text( ctx, box, af_str( &_cutscene.meta.af, strip->strip.pstr_name ), 1, k_ui_align_middle_center, 0 );
          }
       }
 
index 7419468f5547bdbf42abb202de76450cdff0b667..0b157b62e206f5ea6fc292102422bf2e857fcee2 100644 (file)
@@ -52,18 +52,54 @@ struct ms_override
    mdl_transform transform;
 };
 
+enum ms_strip_mode
+{
+   k_ms_strip_mode_keyframes = 0x1,
+   k_ms_strip_mode_curves = 0x2,
+   k_ms_strip_mode_animation = 0x1|0x2,
+
+   k_ms_strip_mode_camera = 0x10,
+   k_ms_strip_mode_event = 0x20,
+   k_ms_strip_mode_subtitle = 0x40,
+   k_ms_strip_mode_fadeout = 0x80,
+};
+
 struct ms_strip
 {
-   u32 data_start,
-       data_count,
-       data_mode,
-       offset,
-       length,
-       pstr_name,
-       pstr_internal_name,
-       instance_id,
-       object_id;
-   f32 timing_offset;
+   u8  mode;
+   u32 offset;
+
+   union
+   {
+      struct
+      {
+         u32 start, count, length,
+             pstr_name,
+             pstr_internal_name,
+             instance_id, object_id;
+         f32 timing_offset;
+      }
+      strip;
+
+      struct
+      {
+         u32 entity_id;
+      }
+      camera;
+
+      struct
+      {
+         u32 pstr_en, res0, res1, res2;
+         u8  character;
+      }
+      subtitle;
+
+      struct
+      {
+         u32 pstr_string;
+      }
+      event;
+   };
 };
 
 struct ms_track
@@ -86,6 +122,11 @@ struct cs_instance
    m4x3f *skinning_data;
 };
 
+struct cs_subtitle
+{
+   const char *key, *value;
+};
+
 #include "skeleton.h"
 
 struct _cutscene
@@ -159,19 +200,16 @@ struct _cutscene
    f32 time;
 
    bool fadeout;
+   u8 skipped;
    f32 fadeout_start, fadeout_cooldown;
 
    const char *marker_this_frame;
    const char *subtitle;
-   struct cs_subtitle
-   {
-      const char *key, *value;
-   }
-   const *subtitle_list;
-   u32 subtitle_index;
    bool subtitle_length_warning;
 
    bool freeze_player;
+
+   u32 raiser_entity;
 }
 extern _cutscene;
 
@@ -179,11 +217,10 @@ void metascene_load( ms_context *ms, const char *path, void *alloc );
 void cutscene_init(void);
 void cutscene_render( world_instance *world, vg_camera *cam );
 void cutscene_render_fadeout(void);
-void _cutscene_load_and_play( const char *path, const cs_subtitle *subtitles, bool freeze_player );
+void _cutscene_load_and_play( const char *path, bool freeze_player, u32 raiser_entity );
 void _cutscene_unload(void);
 void cutscene_update( f32 delta );
 ent_camera *_cutscene_active_camera(void);
 void _cutscene_gui( ui_context *ctx );
-void _cutscene_set_subtitle_list( const cs_subtitle *subtitles );
 
 struct cs_instance *_cutscene_get_first_model_instance( const char *mdl_name );
index f5a53702e46836a947a8d0b7b913cff7eed3d6f2..961f80a63406ffc3343fa8eaca669ce8b29002b7 100644 (file)
@@ -85,6 +85,7 @@ void *mdl_shader_standard( vg_msg *msg, void *alloc )
 {
    struct shader_props_standard *props = vg_linear_alloc( alloc, sizeof(struct shader_props_standard) );
    vg_msg_getkvintg( msg, "tex_diffuse", k_vg_msg_u32, &props->tex_diffuse, NULL );
+   vg_msg_getkvintg( msg, "render_flags", k_vg_msg_u32, &props->render_flags, NULL );
    return props;
 }
 
index b132ea7aaf0d5fd3d8ee6f74fe8891022eaa2c05..e7876ed0f8f4138a79849b71375cbde14b24a629 100644 (file)
@@ -484,12 +484,12 @@ void player_glide_transition(void)
    localplayer.subsystem = k_player_subsystem_glide;
    localplayer.have_glider = 0;
    world_routes_clear( &_world.main );
-
    v3_copy( localplayer.rb.co, player_glide.rb.co );
 
    f32 dir = v3_dot( localplayer.rb.v, localplayer.rb.to_world[2] );
 
-   if( dir > 0.0f ){
+   if( dir > 0.0f )
+   {
       v4f qyaw;
       q_axis_angle( qyaw, (v3f){0,1,0}, VG_TAUf*0.5f );
       q_mul( qyaw, localplayer.rb.q, player_glide.rb.q );
index 4393b12a631f5d87fb8313ecac18b3c33004d99f..904b77f7b9099716dc507ef4bd6a7910e7a5d31a 100644 (file)
@@ -30,13 +30,14 @@ void player_get_anim( skeleton_anim *out_anim, const char *name )
    for( u32 i=0; i<af_arrcount( &ms->strips ); i ++ )
    {
       ms_strip *strip = af_arritm( &ms->strips, i );
-      
-      if( af_str_eq( &ms->af, strip->pstr_name, name, hash ) )
+      if( strip->mode != k_ms_strip_mode_keyframes )
+         continue;
+
+      if( af_str_eq( &ms->af, strip->strip.pstr_name, name, hash ) )
       {
          out_anim->strip = strip;
          out_anim->framerate = localplayer.animations.info.framerate;
-         out_anim->keyframes_base = 
-            af_arritm( &localplayer.animations.keyframes, strip->data_start );
+         out_anim->keyframes_base = af_arritm( &localplayer.animations.keyframes, strip->strip.start );
          return;
       }
    }
@@ -567,6 +568,7 @@ void render_playermodel( vg_camera *cam, world_instance *world,
    shader_model_character_view_uCamera( cam->transform[3] );
    shader_model_character_view_uPv( cam->mtx.pv );
    shader_model_character_view_uDepthMode( depth_compare );
+   shader_model_character_view_uShadeless( 0 );
    if( depth_compare )
    {
       depth_compare_bind(
index 569ef943fabaa5b35361e42194c71b533d3b8ab8..53e6cf8502bfb667140d85b021e94601b4bfb375 100644 (file)
@@ -1262,8 +1262,8 @@ void player__skate_pre_update(void){
    {
       localplayer.subsystem = k_player_subsystem_walk;
 
-      if( (state->activity <= k_skate_activity_air_to_grind) &&
-           localplayer.have_glider ){
+      if( (state->activity <= k_skate_activity_air_to_grind) && localplayer.have_glider )
+      {
          player_glide_transition();
          return;
       }
@@ -3378,7 +3378,7 @@ void player__skate_pose( void *_animator, player_pose *pose ){
       v3_copy( world_view[3], pose->root_co );
 
       f32 t        = animator->handplant_t,
-          frames   = anim->strip->length-1,
+          frames   = anim->strip->strip.length-1,
           length   = animator->activity == k_skate_activity_handplant?
                         frames / anim->framerate:
                         999999,
index 270f3925b41fa185e1e9f827c4b2c935b21a3e4b..ff43934e5c4ee57be63aa3dde10130fa17cd5323 100644 (file)
@@ -248,7 +248,7 @@ static int player_walk_scan_for_drop_in(void){
 
 static bool player__preupdate_anim( struct skeleton_anim *anim, f32 *t, f32 speed )
 {
-   f32 length = (f32)(anim->strip->length-1) / anim->framerate;
+   f32 length = (f32)(anim->strip->strip.length-1) / anim->framerate;
    *t += (vg.time_delta * speed) / length;
    if( *t >= 1.0f ) return 1;
    else             return 0;
@@ -856,7 +856,7 @@ static void player_walk_animate_drop_in(void)
    struct player_walk_animator *animator = &w->animator;
    struct skeleton_anim *anim = &w->anim_drop_in;
 
-   f32 length = (f32)(anim->strip->length-1) / anim->framerate,
+   f32 length = (f32)(anim->strip->strip.length-1) / anim->framerate,
        time   = w->state.transition_t;
 
    f32 walk_yaw = vg_alerpf( w->state.drop_in_start_angle, 
@@ -940,8 +940,8 @@ void player__walk_animate(void){
    }
 
    if( animator->run > 0.025f ){
-      f32 walk_norm = 30.0f/(float)w->anim_walk.strip->length,
-          run_norm  = 30.0f/(float)w->anim_run.strip->length,
+      f32 walk_norm = 30.0f/(float)w->anim_walk.strip->strip.length,
+          run_norm  = 30.0f/(float)w->anim_run.strip->strip.length,
           l;
 
       if( animator->run <= k_walkspeed )
@@ -981,8 +981,7 @@ void player__walk_animate(void){
    }
 }
 
-static void player_walk_pose_sit( struct player_walk_animator *animator,
-                                  player_pose *pose )
+static void player_walk_pose_sit( struct player_walk_animator *animator, player_pose *pose )
 {
    ms_keyframe bpose[32];
 
@@ -990,7 +989,7 @@ static void player_walk_pose_sit( struct player_walk_animator *animator,
    struct skeleton *sk = &localplayer.skeleton;
 
    f32 t  = animator->transition_t,
-       st = t * ((f32)(w->anim_sit.strip->length-1)/30.0f);
+       st = t * ((f32)(w->anim_sit.strip->strip.length-1)/30.0f);
    skeleton_sample_anim( sk, &w->anim_sit, st, bpose );
 
    v4f qy,qp;
@@ -1026,7 +1025,7 @@ static void player_walk_pose_transition(
    struct player_walk *w = &player_walk;
    struct skeleton *sk = &localplayer.skeleton;
    
-   f32 length   = (f32)(anim->strip->length-1) / anim->framerate,
+   f32 length   = (f32)(anim->strip->strip.length-1) / anim->framerate,
        t        = animator->transition_t * length,
        blend    = 1.0f;
 
@@ -1066,8 +1065,8 @@ void player__walk_pose( void *_animator, player_pose *pose ){
    pose->board.lean = 0.0f;
    pose->type = k_player_pose_type_ik;
 
-   float walk_norm = (float)w->anim_walk.strip->length/30.0f,
-         run_norm  = (float)w->anim_run.strip->length/30.0f,
+   float walk_norm = (float)w->anim_walk.strip->strip.length/30.0f,
+         run_norm  = (float)w->anim_run.strip->strip.length/30.0f,
          t = animator->walk_timer;
 
    /* walk/run */
index 24b3d164e8bfc6065ec0f5462d96c04cb9012859..385a4defb3e5cfcb9091a6d4f13ff3bcb99432cb 100644 (file)
@@ -1,6 +1,7 @@
 static bool _skaterift_script_city( ent_script_event *event )
 {
-   if( on_nugget_once( event, "ch3s1_view" ) )
+#if 0
+   if( on_atom_once( event, "ch3s1_view" ) )
    {
       static const struct cs_subtitle EN[] = 
       {
@@ -18,8 +19,8 @@ static bool _skaterift_script_city( ent_script_event *event )
    // REgion complete
    if( on_function_trigger( event, 5 ) )
    {
-      if( _skaterift_script_nugget_status( "ch3s2_view" ) == 0 )
-         _skaterift_script_nugget_set( "ch3s2_view", 2 );
+      if( _skaterift_atom_status( "ch3s2_view" ) == 0 )
+         _skaterift_atom_set( "ch3s2_view", 2 );
    }
 
    // On activate finale challenge
@@ -30,31 +31,33 @@ static bool _skaterift_script_city( ent_script_event *event )
    // On complete finale challenge
    if( on_function_trigger( event, 8 ) )
    {
-      _skaterift_script_nugget_set( "city_finale", 3 );
-      _skaterift_script_nugget_set( "ch3s3_view", 2 );
+      _skaterift_atom_set( "city_finale", 3 );
+      if( _skaterift_atom_status( "ch3s3_view" ) == 0 )
+         _skaterift_atom_set( "ch3s3_view", 2 );
    }
 
    u64 status;
-   if( on_nugget_changed( event, "city_finale", &status ) )
+   if( on_atom_changed( event, "city_finale", &status ) )
    {
       _ent_list_set_visible( _ent_list_get_aliased( "finale" ), status > 0 );
       _ent_list_set_visible( _ent_list_get_aliased( "finale_marker" ), status == 2 );
    }
-
+#endif
    return 1;
 }
 
 static bool _skaterift_script_ch3s2( ent_script_event *event )
 {
+#if 0
    u64 status;
-   if( on_nugget_changed( event, "ch3s2_view", &status ) )
+   if( on_atom_changed( event, "ch3s2_view", &status ) )
       _ent_list_set_visible( event->entity_list, status == 2 );
 
    if( on_function_trigger( event, 0 ) )
    {
-      if( on_nugget_once( event, "ch3s2_view" ) )
+      if( on_atom_once( event, "ch3s2_view" ) )
       {
-         _skaterift_script_nugget_set( "city_finale", 2 );
+         _skaterift_atom_set( "city_finale", 2 );
 
          static const struct cs_subtitle EN[] = 
          {
@@ -68,6 +71,7 @@ static bool _skaterift_script_ch3s2( ent_script_event *event )
          _cutscene_load_and_play( "metascenes/ch3s2.ms", EN, 1 );
       }
    }
+#endif
    return 1;
 }
 
@@ -78,6 +82,7 @@ struct script_ch3s3_waiter
 
 static bool _skaterift_script_ch3s3( ent_script_event *event )
 {
+#if 0
    if( event->type == k_escript_event_allocate )
    {
       struct script_event_allocate *event_info = event->info;
@@ -89,14 +94,14 @@ static bool _skaterift_script_ch3s3( ent_script_event *event )
    struct script_ch1s6a_waiter *waiter = event->userdata;
 
    u64 status;
-   if( on_nugget_changed( event, "ch3s3_view", &status ) )
+   if( on_atom_changed( event, "ch3s3_view", &status ) )
       _ent_list_set_visible( event->entity_list, status == 2 );
 
    if( on_function_trigger( event, 0 ) )
    {
-      if( on_nugget_once( event, "ch3s3_view" ) )
+      if( on_atom_once( event, "ch3s3_view" ) )
       {
-         _skaterift_script_nugget_set( "unlock_valley", 1 );
+         _skaterift_atom_set( "unlock_valley", 1 );
 
          static const struct cs_subtitle EN[] = 
          {
@@ -151,5 +156,6 @@ static bool _skaterift_script_ch3s3( ent_script_event *event )
          }
       }
    }
+#endif
    return 1;
 }
diff --git a/src/scripts/cutscene.c b/src/scripts/cutscene.c
new file mode 100644 (file)
index 0000000..62dc14b
--- /dev/null
@@ -0,0 +1,46 @@
+struct script_cutscene
+{
+   const char *path;
+   bool immobilize;
+};
+
+static bool _skaterift_script_cutscene( ent_script_event *event )
+{
+   if( event->type == k_escript_event_allocate )
+   {
+      struct script_event_allocate *event_info = event->info;
+      struct script_cutscene *cs = vg_linear_alloc( event_info->heap, sizeof(struct script_cutscene) );
+      cs->path = NULL;
+      cs->immobilize = 1;
+      event_info->userdata = cs;
+      return 1;
+   }
+
+   struct script_cutscene *cs = event->userdata;
+
+   if( event->type == k_escript_event_world_event )
+   {
+      struct script_event_world_io *inf = event->info;
+      world_instance *world = &_world.main;
+
+           if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "play" ) )
+      {
+         _cutscene_load_and_play( cs->path, cs->immobilize, inf->event->recieve_entity_id );
+      }
+      else if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "immobilize" ) ) 
+      {
+         // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
+         if( inf->event->flags == k_ent_event_data_const_i32 )
+            cs->immobilize = inf->event->data.const_i32;
+         else vg_error( "a300\n" );
+      }
+      else if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "path" ) ) 
+      {
+         if( inf->event->flags == k_ent_event_data_const_string )
+            cs->path = af_str( &world->meta.af, inf->event->data.const_pstr );
+         else vg_error( "a300\n" );
+      }
+   }
+   
+   return 1;
+}
diff --git a/src/scripts/explode.c b/src/scripts/explode.c
new file mode 100644 (file)
index 0000000..cb8304e
--- /dev/null
@@ -0,0 +1,47 @@
+static bool _skaterift_script_explode( ent_script_event *event )
+{
+   if( event->type == k_escript_event_world_event )
+   {
+      struct script_event_world_io *inf = event->info;
+      world_instance *world = &_world.main;
+      if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "explode" ) ) 
+      {
+         // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
+         if( inf->event->flags & k_ent_event_data_const_entity_id )
+         {
+            u32 breaklist_id = inf->event->data.const_entity_id;
+            if( mdl_entity_id_type( breaklist_id ) != k_ent_list )
+            {
+               vg_error( "explode called with not a list\n" );
+               return 0;
+            }
+
+            ent_list *list = af_arritm( &world->ent_list, mdl_entity_id_id(breaklist_id) );
+            _ent_list_set_visible( list, 0 );
+            v3f where = {0,0,0};
+
+            struct ent_list_iter iter;
+            _ent_list_iter_start( &iter, list, 0 );
+
+            while( _ent_list_iter( &iter ) )
+            {
+               if( iter.type == k_ent_marker )
+               {
+                  ent_marker *marker = af_arritm( &world->ent_marker, iter.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();
+         }
+      }
+   }
+   
+   return 1;
+}
index 97c008cca53a2bee1311e39a53b020401cc23b60..9b5bf4736f9b320daec7cdc93ebd8b375f162d04 100644 (file)
@@ -17,7 +17,7 @@ static bool _skaterift_script_board_maker_unlock( ent_script_event *event )
    }
 
    u64 status;
-   if( on_nugget_changed( event, "board_maker_unlock", &status ) )
+   if( on_atom_changed( event, "board_maker_unlock", &status ) )
    {
       struct board_maker_unlock_waiter *waiter = event->userdata;
       waiter->changed = 1;
index 690e76c2dffa395cb189a39d3b9b721d5677d897..5f9dfbe65e6212eba3f50e4d6ae57b5052a54bfe 100644 (file)
@@ -5,6 +5,7 @@ struct script_hub
 
 static bool _skaterift_script_hub( ent_script_event *event )
 {
+#if 0
    if( event->type == k_escript_event_allocate )
    {
       struct script_event_allocate *event_info = event->info;
@@ -16,54 +17,79 @@ static bool _skaterift_script_hub( ent_script_event *event )
 
    struct script_hub *script_hub = event->userdata;
 
-   /* small text box pop up, the welcome thing. */
-   if( on_function_trigger( event, 0 ) )
+   if( on_completion_changed(event) )
    {
-      if( on_nugget_once( event, "hub_info_view" ) )
-         menu_open( k_menu_page_impromptu_guide );
-   }
+      u64 progress = _skaterift_atom_status( "story" );
 
-   struct 
-   {
-      const char *ms, *nugget, *view_nugget, *list;
-   }
-   blocks[] =
-   {
-      { "metascenes/unlock_mtzero.ms", "unlock_mtzero", "unlock_mtzero_view", "mtzero:locked" },
-      { "metascenes/unlock_city.ms",   "unlock_city",   "unlock_city_view",   "city:locked" },
-      { "metascenes/unlock_valley.ms", "unlock_valley", "unlock_valley_view", "valley:locked" },
-   };
+      /* blockers
+       * ------------------------------------------------------------------------ */
+      struct 
+      {
+         const char *ms, *stage, *view_atom, *list_name;
+         bool unlocked;
+      }
+      blocks[] =
+      {
+         { "metascenes/unlock_mtzero.ms", "mz",     "unlock_mtzero_view", "mtzero:locked" },
+         { "metascenes/unlock_city.ms",   "city",   "unlock_city_view",   "city:locked" },
+         { "metascenes/unlock_valley.ms", "valley", "unlock_valley_view", "valley:locked" },
+      };
 
-   for( u32 i=0; i<VG_ARRAY_LEN(blocks); i ++ )
-   {
-      u64 status;
-      if( on_nugget_changed( event, blocks[i].nugget, &status ) )
+      i32 highest_index = -1;
+      for( i32 i=0; i<VG_ARRAY_LEN(blocks); i ++ )
+      {
+         blocks[i].unlocked = 0;
+         ent_list *list = _ent_list_get_aliased( blocks[i].list_name );
+         if( progress >= _skaterift_atom_enum_index( "story", blocks[i].stage, ATOM_MAX ) )
+         {
+            blocks[i].unlocked = 1;
+            _ent_list_set_visible( list, 0 );
+            highest_index = i;
+         }
+         else
+            _ent_list_set_visible( list, 1 );
+      }
+
+      if( highest_index != -1 )
       {
-         ent_list *list = _ent_list_get_aliased( blocks[i].list );
-         if( status == 1 )
+         ent_list *list = _ent_list_get_aliased( blocks[highest_index].list_name );
+         if( on_atom_once( event, blocks[highest_index].view_atom ) )
          {
-            if( on_nugget_once( event, blocks[i].view_nugget ) )
-            {
-               _cutscene_load_and_play( blocks[i].ms, NULL, 1 );
-               script_hub->break_list = list;
-            }
-            else
-               _ent_list_set_visible( list, 0 );
+            _cutscene_load_and_play( blocks[highest_index].ms, NULL, 1 );
+            _ent_list_set_visible( list, 1 );
+            script_hub->break_list = list;
          }
+         else
+            _ent_list_set_visible( list, 0 );
+      }
+
+      /* spawns locked behind the boxes 
+       * ------------------------------------------------------------------------ */
+      world_instance *world = &_world.main;
+      u32 spawns_allowed = 0;
+      if( blocks[0].unlocked ) spawns_allowed |= k_ent_spawn_flag_group_1;
+      if( blocks[1].unlocked ) spawns_allowed |= k_ent_spawn_flag_group_2;
+      if( blocks[2].unlocked ) spawns_allowed |= k_ent_spawn_flag_group_3;
+      for( u32 i=0; i<af_arrcount(&world->ent_spawn); i++ )
+      {
+         ent_spawn *spawn = af_arritm( &world->ent_spawn, i );
+         bool allow = 0;
+
+         if( spawn->flags == 0 ) allow = 1;
+         if( spawn->flags & spawns_allowed ) allow = 1;
+
+         if( allow ) spawn->flags &= ~(u32)k_ent_spawn_flag_locked;
+         else        spawn->flags |= k_ent_spawn_flag_locked;
       }
    }
 
    if( on_cutscene_marker( event, "$break" ) )
       _explode_template_boom( script_hub->break_list );
 
-   if( event->type == k_escript_event_nugget_changed )
+   if( on_world_start( event ) )
    {
+      // TODO: Move these into atoms?
       world_instance *world = &_world.main;
-
-      bool unlock_mtzero = _skaterift_script_nugget_status( "unlock_mtzero" ),
-           unlock_city   = _skaterift_script_nugget_status( "unlock_city" ),
-           unlock_valley = _skaterift_script_nugget_status( "unlock_valley" );
-
       for( u32 i=0; i<af_arrcount( &world->ent_prop ); i ++ )
       {
          ent_prop *prop = af_arritm( &world->ent_prop, i );
@@ -84,47 +110,23 @@ static bool _skaterift_script_hub( ent_script_event *event )
             if( skaterift.achievements & 0x8 )
                prop->flags &= ~0x1;
       }
-
-      u32 spawns_allowed = 0;
-      if( unlock_mtzero ) spawns_allowed |= k_ent_spawn_flag_group_1;
-      if( unlock_city ) spawns_allowed |= k_ent_spawn_flag_group_2;
-      if( unlock_valley ) spawns_allowed |= k_ent_spawn_flag_group_3;
-
-      for( u32 i=0; i<af_arrcount(&world->ent_spawn); i++ )
-      {
-         ent_spawn *spawn = af_arritm( &world->ent_spawn, i );
-
-         bool allow = 0;
-
-         if( spawn->flags == 0 ) allow = 1;
-         if( spawn->flags & spawns_allowed ) allow = 1;
-
-         if( allow ) spawn->flags &= ~(u32)k_ent_spawn_flag_locked;
-         else        spawn->flags |= k_ent_spawn_flag_locked;
-      }
-
-      return 1;
    }
 
-   u64 status;
-   if( on_nugget_changed( event, "board_maker_unlock", &status ) )
+   /* gino helper board maker thing
+    * ------------------------------------------------------------------------ */
+   if( event->type == k_escript_event_atom_changed )
    {
-      ent_list *list = _ent_list_get_aliased( "gino_board_maker" );
       bool visible = 0;
-
-      if( status )
-      {
-         u64 view = _skaterift_script_nugget_status( "board_maker_hub_view" );
-         if( view == 0 )
+      if( _skaterift_atom_status( "board_maker_unlock" ) )
+         if( _skaterift_atom_status( "board_maker_hub_view" ) == 0 )
             visible = 1;
-      }
 
-      _ent_list_set_visible( list, visible );
+      _ent_list_set_visible( _ent_list_get_aliased( "gino_board_maker" ), visble );
    }
 
    if( on_function_trigger( event, 5 ) )
    {
-      _skaterift_script_nugget_set( "board_maker_hub_view", 1 );
+      _skaterift_atom_set( "board_maker_hub_view", 1 );
 
       // Hide just the notifier
       struct ent_list_iter iter;
@@ -136,6 +138,6 @@ static bool _skaterift_script_hub( ent_script_event *event )
          marker->flags |= (u32)k_ent_marker_flag_hidden;
       }
    }
-
+#endif
    return 0;
 }
index 3efeb4fbee61f35f573d592c540e82f8b20e7dc5..ef728d7f2cb649322289eef1f814affbfed9fbd0 100644 (file)
@@ -1,7 +1,8 @@
 static bool _skaterift_script_mtzero( ent_script_event *event )
 {
+#if 0
    /* intro movie */
-   if( on_nugget_once( event, "ch2s1_view" ) )
+   if( on_atom_once( event, "ch2s1_view" ) )
    {
       static const struct cs_subtitle EN[] = 
       {
@@ -40,9 +41,10 @@ static bool _skaterift_script_mtzero( ent_script_event *event )
       }
 
       if( requirements_met )
-         if( _skaterift_script_nugget_status( "ch2s3_view" ) == 0 )
-            _skaterift_script_nugget_set( "ch2s3_view", 2 );
+         if( _skaterift_atom_status( "ch2s3_view" ) == 0 )
+            _skaterift_atom_set( "ch2s3_view", 2 );
    }
+#endif
 
    return 1;
 }
@@ -54,9 +56,10 @@ static bool _skaterift_script_mtzero_after( ent_script_event *event )
 
 static bool _skaterift_script_ch2s2( ent_script_event *event )
 {
+#if 0
    if( on_function_trigger( event, 0 ) )
    {
-      if( on_nugget_once( event, "ch2s2_view" ) )
+      if( on_atom_once( event, "ch2s2_view" ) )
       {
          static const struct cs_subtitle EN[] = 
          {
@@ -80,16 +83,18 @@ static bool _skaterift_script_ch2s2( ent_script_event *event )
       }
    }
    u64 status;
-   if( on_nugget_changed( event, "ch2s2_view", &status ) )
+   if( on_atom_changed( event, "ch2s2_view", &status ) )
       _ent_list_set_visible( event->entity_list, status == 0 );
+#endif
    return 1;
 }
 
 static bool _skaterift_script_ch2s3( ent_script_event *event )
 {
+#if 0
    if( on_function_trigger( event, 0 ) )
    {
-      if( on_nugget_once( event, "ch2s3_view" ) )
+      if( on_atom_once( event, "ch2s3_view" ) )
       {
          static const struct cs_subtitle EN[] = 
          {
@@ -177,33 +182,37 @@ static bool _skaterift_script_ch2s3( ent_script_event *event )
       }
    }
    u64 status;
-   if( on_nugget_changed( event, "ch2s3_view", &status ) )
+   if( on_atom_changed( event, "ch2s3_view", &status ) )
       _ent_list_set_visible( event->entity_list, status == 2 );
+#endif
    return 1;
 }
 
 static bool _skaterift_script_ch2s5_before( ent_script_event *event )
 {
+#if 0
    u64 status;
-   if( on_nugget_changed( event, "ch2s5_view", &status ) )
+   if( on_atom_changed( event, "ch2s5_view", &status ) )
       _ent_list_set_visible(  event->entity_list, status == 2 );
 
    if( on_function_trigger( event, 0 ) )
    {
-      _skaterift_script_nugget_set( "ch2s5_view", 3 );
+      _skaterift_atom_set( "ch2s5_view", 3 );
       skaterift_load_world_command( 1, (const char *[]){ "reload" } );
    }
+#endif
    return 1;
 }
 
 static bool _skaterift_script_ch2s5_after( ent_script_event *event )
 {
+#if 0
    u64 status;
-   if( on_nugget_changed( event, "ch2s5_view", &status ) )
+   if( on_atom_changed( event, "ch2s5_view", &status ) )
    {
       if( status == 3 )
       {
-         _skaterift_script_nugget_set( "ch2s5_view", 1 );
+         _skaterift_atom_set( "ch2s5_view", 1 );
          static const struct cs_subtitle EN[] = 
          {
             { "m1",  KCOL_MIKE "Hi mate, hows it goin?" },
@@ -221,6 +230,7 @@ static bool _skaterift_script_ch2s5_after( ent_script_event *event )
          _cutscene_load_and_play( "metascenes/ch2s5.ms", EN, 1 );
       }
    }
+#endif
    return 1;
 }
 
@@ -231,6 +241,7 @@ struct script_ch2s6_waiter
 
 static bool _skaterift_script_ch2s6( ent_script_event *event )
 {
+#if 0
    if( event->type == k_escript_event_allocate )
    {
       struct script_event_allocate *event_info = event->info;
@@ -242,17 +253,17 @@ static bool _skaterift_script_ch2s6( ent_script_event *event )
    struct script_ch2s6_waiter *waiter = event->userdata;
 
    u64 status;
-   if( on_nugget_changed( event, "ch2s6_view", &status ) )
+   if( on_atom_changed( event, "ch2s6_view", &status ) )
       _ent_list_set_visible( event->entity_list, status == 2 );
 
    // TODOX1: THERE ARE NO UNLOCK CONDITIONS FOR THIS YET!
 
    if( on_function_trigger( event, 0 ) )
    {
-      if( on_nugget_once( event, "ch2s6_view" ) )
+      if( on_atom_once( event, "ch2s6_view" ) )
       {
-         _skaterift_script_nugget_set( "unlock_city", 1 );
-         _skaterift_script_nugget_set( "ch2s6_view", 1 );
+         _skaterift_atom_set( "unlock_city", 1 );
+         _skaterift_atom_set( "ch2s6_view", 1 );
          static const struct cs_subtitle EN[] = 
          {
             { "j1",  KCOL_JOHN "Ello guys" },
@@ -287,16 +298,18 @@ static bool _skaterift_script_ch2s6( ent_script_event *event )
          }
       }
    }
+#endif
    return 1;
 }
 
 static bool _skaterift_script_ch2e1( ent_script_event *event )
 {
+#if 0
    if( on_function_trigger( event, 0 ) )
    {
-      if( on_nugget_once( event, "ch2e1_view" ) )
+      if( on_atom_once( event, "ch2e1_view" ) )
       {
-         _skaterift_script_nugget_set( "board_maker_unlock", 1 );
+         _skaterift_atom_set( "board_maker_unlock", 1 );
          static const struct cs_subtitle EN[] = 
          {
             { "j1",  KCOL_JOHN "Hey bird I'm just working on some boards here." },
@@ -310,8 +323,9 @@ static bool _skaterift_script_ch2e1( ent_script_event *event )
       }
    }
    u64 status;
-   if( on_nugget_changed( event, "ch2e1_view", &status ) )
+   if( on_atom_changed( event, "ch2e1_view", &status ) )
       _ent_list_set_visible( event->entity_list, status == 2 );
+#endif
    return 1;
 }
 
@@ -324,6 +338,7 @@ struct script_ch2s4_waiter
 
 static bool _skaterift_script_battery_jump( ent_script_event *event )
 {
+#if 0
    if( event->type == k_escript_event_allocate )
    {
       struct script_event_allocate *event_info = event->info;
@@ -340,16 +355,16 @@ static bool _skaterift_script_battery_jump( ent_script_event *event )
 
    if( on_function_trigger( event, 2 ) )
    {
-      if( on_nugget_once( event, "ch2s4_view" ) )
+      if( on_atom_once( event, "ch2s4_view" ) )
       {
-         _skaterift_script_nugget_set( "ch2s5_view", 2 );
+         _skaterift_atom_set( "ch2s5_view", 2 );
          waiter->go = 1;
       }
    }
 
    /* viewed ch2s3 means we allowing this challenge now */
    u64 status;
-   if( on_nugget_changed( event, "ch2s3_view", &status ) )
+   if( on_atom_changed( event, "ch2s3_view", &status ) )
       _ent_list_set_visible( event->entity_list, status == 1 );
 
    if( event->type == k_escript_event_update )
@@ -385,7 +400,7 @@ static bool _skaterift_script_battery_jump( ent_script_event *event )
 
    if( on_function_trigger( event, 0 ) )
    {
-      if( on_nugget_once( event, "battery_jump_view" ) )
+      if( on_atom_once( event, "battery_jump_view" ) )
       {
          _cutscene_load_and_play( "metascenes/battery_intro.ms", NULL, 1 );
          waiter->break_list = _ent_list_get_aliased( "battery:locked" );
@@ -395,8 +410,8 @@ static bool _skaterift_script_battery_jump( ent_script_event *event )
    if( event->type == k_escript_event_world_start )
    {
       _ent_list_set_visible( _ent_list_get_aliased( "battery:locked" ), 
-                             _skaterift_script_nugget_status( "battery_jump_view" ) == 0 );
+                             _skaterift_atom_status( "battery_jump_view" ) == 0 );
    }
-
+#endif
    return 1;
 }
index c8945f3e579bdf25b712bc8f45193fbe0998ffa4..740fcf6af43dc610c04874bd8d3cbc668b7cb0d0 100644 (file)
@@ -7,6 +7,24 @@ struct script_volcano
 
 static bool _skaterift_script_tutorial_island( ent_script_event *event )
 {
+#if 0
+   if( on_advancement(event) )
+   {
+      ent_list *region0_challenges = _ent_list_get_aliased( "region0" );
+      bool region0_is_target = 0;
+
+      u64 progress = _skaterift_atom_status( "story" );
+      if( progress == _skaterift_atom_enum_index( "story", "volc" ) )
+      {
+         if( _ent_list_check_completed( region0_challenges ) )
+            region0_is_target = 0;
+         else
+            region0_is_target = 1;
+      }
+
+      _ent_list_set_as_targets( region0_challenges, region0_is_target );
+   }
+
    if( event->type == k_escript_event_allocate )
    {
       struct script_event_allocate *event_info = event->info;
@@ -20,36 +38,37 @@ static bool _skaterift_script_tutorial_island( ent_script_event *event )
 
    struct script_volcano *script_volcano = event->userdata;
 
-   if( on_cutscene_marker( event, "$break" ) )
-      _explode_template_boom( script_volcano->break_list );
-
-   /* intro movie */
-   if( on_nugget_once( event, "ch1s2_view" ) )
-   {
-      static const struct cs_subtitle EN[] = {
-      { "john_1", KCOL_JOHN "Well, here we are. Home." },
-      { "john_2", KCOL_JOHN "I mean, halfway home." },
-      { "john_3", KCOL_JOHN "Obviously you've forgotten quite a bit, so we'll stop off here" },
-      { "john_4", KCOL_JOHN "and I'll teach you some stuff again" },
-      { NULL, NULL },
-      };
-      _cutscene_load_and_play( "metascenes/ch1s2.ms", EN, 1 );
-   }
-
-   /* all tasks completed (called from the region entity) */
-   if( on_function_trigger( event, 2 ) )
+   if( on_completion_changed(event) )
    {
-      ent_list *list = _ent_list_get_aliased( "docks:locked" );
-      if( on_nugget_once( event, "unlock_docks_view" ) )
+      u64 progress = _skaterift_atom_status( "story" );
+      if( progress == _skaterift_atom_enum_index( "story", "volc" ) )
       {
-         vg_low( "waiting for stopped...\n" );
-         _skaterift_script_nugget_set( "ch1s6a_view", 2 );
-         script_volcano->docks_wait = 1;
+         static const struct cs_subtitle EN[] = {
+         { "john_1", KCOL_JOHN "Well, here we are. Home." },
+         { "john_2", KCOL_JOHN "I mean, halfway home." },
+         { "john_3", KCOL_JOHN "Obviously you've forgotten quite a bit, so we'll stop off here" },
+         { "john_4", KCOL_JOHN "and I'll teach you some stuff again" },
+         { NULL, NULL },
+         };
+         _cutscene_load_and_play( "metascenes/ch1s2.ms", EN, 1 );
+         _skaterift_atom_set_enum( "story", "volc:tutorial" );
+      }
+      else if( progress == _skaterift_atom_enum_index( "story", "volc:tutorial" ) )
+      {
+         if( _ent_list_check_completed( _ent_list_get_aliased( "region0" ) ) )
+         {
+            _skaterift_atom_set_enum( "story", "volc:leaving" );
+            vg_low( "waiting for stopped...\n" );
+            script_volcano->docks_wait = 1;
+         }
+      }
+      else if( progress == _skaterift_atom_enum_index( "story", "volc:leaving" ) )
+      {
+         _ent_list_set_visible( _ent_list_get_aliased( "docks:locked" ), 0 );
       }
-      else
-         _ent_list_set_visible( list, 0 );
    }
 
+   /* waiting for player to stop to blow up the docks */
    if( event->type == k_escript_event_update )
    {
       if( script_volcano->docks_wait )
@@ -72,14 +91,19 @@ static bool _skaterift_script_tutorial_island( ent_script_event *event )
       }
    }
 
+   if( on_cutscene_marker( event, "$break" ) )
+      _explode_template_boom( script_volcano->break_list );
+#endif
+
    return 1;
 }
 
 static bool _skaterift_script_ch1s3( ent_script_event *event )
 {
+#if 0
    if( on_function_trigger( event, 1 ) )
    {
-      if( on_nugget_once( event, "ch1s3_view" ) )
+      if( on_atom_once( event, "ch1s3_view" ) )
       {
          static const struct cs_subtitle EN[] = {
          { "john_1", KCOL_JOHN "Alright so, fliptricks." },
@@ -95,7 +119,7 @@ static bool _skaterift_script_ch1s3( ent_script_event *event )
 
    if( on_function_trigger( event, 2 ) )
    {
-      if( on_nugget_once( event, "ch1s3b_view" ) )
+      if( on_atom_once( event, "ch1s3b_view" ) )
       {
          static const struct cs_subtitle EN[] = {
          { "john_1", KCOL_JOHN "That is it mate!" },
@@ -107,18 +131,26 @@ static bool _skaterift_script_ch1s3( ent_script_event *event )
       }
    }
 
+   u64 progress;
+   if( on_atom_changed( event, "story", &progress ) )
+   {
+      bool visible = progress == _skaterift_atom_enum_index( "story", "volc:tutorial" );
+      _ent_list_set_visible( event->entity_list, visible );
+   }
+
    u64 viewed;
-   if( on_nugget_changed( event, "ch1s3_view", &viewed ) )
+   if( on_atom_changed( event, "ch1s3_view", &viewed ) )
       _ent_list_set_visible( event->entity_list, !viewed );
-
+#endif
    return 1;
 }
 
 static bool _skaterift_script_ch1s4( ent_script_event *event )
 {
+#if 0
    if( on_function_trigger( event, 0 ) )
    {
-      if( on_nugget_once( event, "ch1s4_view" ) )
+      if( on_atom_once( event, "ch1s4_view" ) )
       {
          static const struct cs_subtitle EN[] = {
          { "john_1", KCOL_JOHN "Remember these courses we were setting up?" },
@@ -134,17 +166,19 @@ static bool _skaterift_script_ch1s4( ent_script_event *event )
    }
 
    u64 status;
-   if( on_nugget_changed( event, "ch1s4_view", &status ) )
+   if( on_atom_changed( event, "ch1s4_view", &status ) )
       _ent_list_set_visible( event->entity_list, status == 0 );
+#endif
 
    return 1;
 }
 
 static bool _skaterift_script_ch1s5( ent_script_event *event )
 {
+#if 0
    if( on_function_trigger( event, 0 ) )
    {
-      if( on_nugget_once( event, "ch1s5_view" ) )
+      if( on_atom_once( event, "ch1s5_view" ) )
       {
          static const struct cs_subtitle EN[] = {
          /* 50ch| set cc=70 |################################################| */
@@ -189,37 +223,25 @@ static bool _skaterift_script_ch1s5( ent_script_event *event )
          _cutscene_load_and_play( "metascenes/ch1s5.ms", EN, 1 );
       }
    }
+#endif
    return 1;
 }
 
-struct script_ch1s6a_waiter
-{
-   bool go;
-};
-
 static bool _skaterift_script_ch1s6a( ent_script_event *event )
 {
-   if( event->type == k_escript_event_allocate )
+#if 0
+   u64 progress;
+   if( on_atom_changed( event, "story", &progress ) )
    {
-      struct script_event_allocate *event_info = event->info;
-      struct script_ch1s6a_waiter *waiter = vg_linear_alloc( event_info->heap, sizeof(struct script_ch1s6a_waiter) );
-      waiter->go = 0;
-      event_info->userdata = waiter;
-      return 1;
+      bool visible = progress == _skaterift_atom_enum_index( "story", "volc:leaving" );
+      _ent_list_set_visible( event->entity_list, visible );
    }
 
-   struct script_ch1s6a_waiter *waiter = event->userdata;
-   u64 status;
-   if( on_nugget_changed( event, "ch1s6a_view", &status ) )
-      _ent_list_set_visible( event->entity_list, status == 2 );
-
    if( on_function_trigger( event, 0 ) )
    {
-      if( on_nugget_once( event, "ch1s6a_view" ) )
+      _skaterift_atom_set_enum( "story", "mz" );
+      static const struct cs_subtitle EN[] = 
       {
-         _skaterift_script_nugget_set( "unlock_mtzero", 1 );
-
-         static const struct cs_subtitle EN[] = {
          { "j1", KCOL_JOHN "Eyyy! Looks like you're ready again.." },
          { "j2", KCOL_JOHN "Didn't take long" },
          { "j3", KCOL_JOHN "Just a short ferry ride back over to Mt.Zero now." },
@@ -230,22 +252,13 @@ static bool _skaterift_script_ch1s6a( ent_script_event *event )
          { "j9", KCOL_JOHN "yknow, its our home!" },
 
          { NULL, NULL },
-         };
-         _cutscene_load_and_play( "metascenes/ch1s6a.ms", EN, 1 );
-         waiter->go = 1;
-      }
+      };
+      _cutscene_load_and_play( "metascenes/ch1s6a.ms", EN, 1 );
    }
 
-   if( event->type == k_escript_event_update )
-   {
-      if( waiter->go )
-      {
-         if( _cutscene.state == k_cutscene_state_none )
-         {
-            waiter->go = 0;
-            skaterift_load_world_command( 1, (const char *[]){ "sr002-local-dev_hub" } );
-         }
-      }
-   }
+   if( on_cutscene_marker( event, "$ch1s6a_end" ) )
+      skaterift_load_world_command( 1, (const char *[]){ "sr002-local-dev_hub" } );
+#endif
+      
    return 1;
 }
diff --git a/src/scripts/valley.c b/src/scripts/valley.c
new file mode 100644 (file)
index 0000000..727be69
--- /dev/null
@@ -0,0 +1,183 @@
+#if 0
+struct script_valley_waiter
+{
+   bool go;
+};
+
+static bool _skaterift_script_valley( ent_script_event *event )
+{
+   if( event->type == k_escript_event_allocate )
+   {
+      struct script_event_allocate *event_info = event->info;
+      struct script_valley_waiter *waiter = vg_linear_alloc( event_info->heap, sizeof(struct script_valley_waiter) );
+      waiter->go = 0;
+      event_info->userdata = waiter;
+      return 1;
+   }
+   struct script_valley_waiter *waiter = event->userdata;
+
+
+
+
+#if 0
+
+   if( on_atom_once( event, "ch4s1a_view" ) )
+   {
+      /* ch4s1: Mike and you are first encountering the valley world */
+      static const struct cs_subtitle EN[] = 
+      {
+         { "m1",  KCOL_MIKE "It's gotta be some kind of dream right?" },
+         { "m2",  KCOL_MIKE "I mean... Cambodia?" },
+         { "m3",  KCOL_MIKE "What are we even doing here?" },
+         { NULL, NULL },
+      };
+      _cutscene_load_and_play( "metascenes/ch4s1a.ms", EN, 1 );
+   }
+
+   /* main region is completed (this is just the time trial as of 14.05.25, unlock ch4s2 cutscene */
+   if( on_function_trigger( event, 27 ) )
+   {
+      if( _skaterift_atom_status( "ch4s2_view" ) == 0 )
+         _skaterift_atom_set( "ch4s2_view", 2 );
+   }
+
+   u64 status;
+   if( on_atom_changed( event, "valley_finale", &status ) )
+   {
+      _ent_list_set_visible( _ent_list_get_aliased( "finale:locked" ),   status != 1 );
+      _ent_list_set_visible( _ent_list_get_aliased( "finale:unlocked" ), status == 1 );
+   }
+
+   /* finale completed, trigger the exit movie */
+   if( on_function_trigger( event, 21 ) )
+   {
+      _ent_list_set_visible( _ent_list_get_aliased( "rocket" ), 0 );
+      _skaterift_atom_set( "unlock_venus", 1 );
+      waiter->go = 1;
+      if( on_atom_once( event, "rocket_launch_view" ) )
+      {
+         static const struct cs_subtitle EN[] = 
+         {
+            { NULL, NULL },
+         };
+         _cutscene_load_and_play( "metascenes/ch4rk.ms", EN, 1 );
+      }
+   }
+
+   if( on_cutscene_marker( event, "$fast" ) )
+      k_day_length = 0.1f;
+   if( on_cutscene_marker( event, "$normal" ) )
+      k_day_length = 30.0f;
+
+   u64 _0, _1;
+   if( on_atom_changed( event, "valley_finale", &_0 ) || on_atom_changed( event, "unlock_venus", &_1 ) )
+   {
+      // Notification & video tape
+      bool visible = _skaterift_atom_status( "valley_finale" );
+      bool completed = _skaterift_atom_status( "unlock_venus" );
+      _ent_list_set_visible( _ent_list_get_aliased( "finale_not_done" ), visible && !completed );
+   }
+
+   if( event->type == k_escript_event_update )
+   {
+      if( waiter->go )
+      {
+         if( _cutscene.state == k_cutscene_state_none )
+         {
+            waiter->go = 0;
+            skaterift_load_world_command( 1, (const char *[]){ "sr002-local-venus" } );
+         }
+      }
+   }
+
+#endif
+   return 1;
+}
+
+static bool _skaterift_script_ch4s2( ent_script_event *event )
+{
+   /* ch4s2: Mike and you find the rocket, and talk to the FBI person. */
+   u64 status;
+   if( on_atom_changed( event, "ch4s2_view", &status ) )
+   {
+      _ent_list_set_visible( event->entity_list, status == 2 );
+
+      bool launched = _skaterift_atom_status( "unlock_venus" );
+      _ent_list_set_visible( _ent_list_get_aliased( "rocket" ), (status >= 1) && !(launched) );
+   }
+
+   if( on_function_trigger( event, 0 ) )
+   {
+      if( on_atom_once( event, "ch4s2_view" ) )
+      {
+         _skaterift_atom_set( "valley_cave", 1 );
+         _ent_npc_set_in_cutscene( k_npc_fbi, 1 );
+
+         static const struct cs_subtitle EN[] = 
+         {
+            { "m1",  KCOL_MIKE "What the hell is that thing?" },
+            { "f1",  KCOL_FBI  "Look man, all they told is that uhh" },
+            { "f2",  KCOL_FBI  "they're sending you up to one of saturns moons.." },
+            { "f3",  KCOL_FBI  "On that thing." },
+            { "f4",  KCOL_FBI  "To help you on your mission." },
+            { "f5",  KCOL_FBI  "You guys are more important than any person on earth right now" },
+            { "f6",  KCOL_FBI  "According to the president." },
+            { "f7",  KCOL_FBI  "But obviously this is some kind of joke I'm not in on." },
+            { "f8",  KCOL_FBI  "I don't believe a word of it." },
+            { NULL, NULL },
+         };
+         _cutscene_load_and_play( "metascenes/ch4s2.ms", EN, 1 );
+      }
+   }
+
+   return 1;
+}
+
+static bool _skaterift_script_ch4s1( ent_script_event *event )
+{
+   u64 _0, _1;
+   if( on_atom_changed( event, "valley_cave", &_0 ) || on_atom_changed( event, "valley_finale", &_1 ) )
+   {
+      // Notification & video tape
+      bool visible = _skaterift_atom_status( "valley_cave" );
+      bool completed = _skaterift_atom_status( "valley_finale" );
+      _ent_list_set_visible( _ent_list_get_aliased( "cave_not_done" ), visible && !completed );
+      _ent_list_set_visible( event->entity_list, visible );
+   }
+
+   /* triggers on challenge activating */
+   if( on_function_trigger( event, 3 ) )
+   {
+      /* ch4s1: (Yes, this comes after ch4s2), Mike is leaving, because JC hasn't shown up anywhere. */
+      if( on_atom_once( event, "ch4s1_view" ) )
+      {
+         static const struct cs_subtitle EN[] = 
+         {
+         { "m1",  KCOL_MIKE "John hasn't turned up anywhere.." },
+         { "m2",  KCOL_MIKE "Not here, not back in Australia" },
+         { "m3",  KCOL_MIKE "nowhere?" },
+         { "m4",  KCOL_MIKE "I don't know how we can trust a single note.." },
+         { "m5",  KCOL_MIKE "I mean it is JC but.." },
+         { "m6",  KCOL_MIKE "Come on." },
+         { "m7",  KCOL_MIKE "I havn't seen him in weeks" },
+         { "m8",  KCOL_MIKE "I'm gonna go home," },
+         { "m9",  KCOL_MIKE "I'm bailing on this one man I'm sorry." },
+         { NULL, NULL },
+         };
+         _cutscene_load_and_play( "metascenes/ch4s1.ms", EN, 1 );
+      }
+   }
+   
+   /* triggers on challenge completed */
+   if( on_function_trigger( event, 6 ) )
+      _skaterift_atom_set( "valley_finale", 1 );
+
+   return 1;
+}
+
+static bool _skaterift_script_ch4s3( ent_script_event *event )
+{
+   // on venus
+   return 1;
+}
+#endif
index 05f9ef03eef5ac178e31cab6801d8eef38b152fc..43cf6ff02dfa38bd0f695bfd96ab92618404e124 100644 (file)
@@ -1,9 +1,15 @@
 #pragma once
 #include "vg/vg_platform.h"
 
+enum material_render_flag
+{
+   k_material_render_additive = 0x20
+};
+
 struct shader_props_standard
 {
    u32 tex_diffuse;
+   u32 render_flags;
 };
 
 struct shader_props_terrain
index b78e32302c41cb5846f1c5c5abea12d9b2024bfe..fea4120d2e291c9e8816520fe178084fa7665a8e 100644 (file)
@@ -348,8 +348,6 @@ static void render_scene(void)
 {
 }
 
-m4x3f *_TEMP_VAR = NULL; /*FIXME*/
-
 static void skaterift_composite_maincamera(void)
 {
    /* world entity driven camera 
@@ -399,12 +397,6 @@ static void skaterift_composite_maincamera(void)
 
    vg_camera_update_transform( &g_render.cam );
 
-   if( _TEMP_VAR )
-   {
-      m4x3_copy( _TEMP_VAR[0], g_render.cam.transform );
-      _TEMP_VAR = NULL;
-   }
-
    vg_camera_update_view( &g_render.cam );
    vg_camera_update_projection( &g_render.cam, vg.window_x, vg.window_y );
    vg_camera_finalize( &g_render.cam );
index e70cef5438f9804a55eef38b1ef3833d99155cd1..a585bda0ab613457b1c6f507a727ae2121654925 100644 (file)
 
 #include "ent_script.h"
 
-
-
-#if 0
-
-#include "entity.h"
-#include "ent_challenge.h"
-
-
-static bool _skaterift_script_tutorial_setup( enum escript_event ev, const char *inf )
+const char *_script_linear_story[] = 
 {
-   if( ev == k_escript_event_call )
-   {
-      /* TODO: Attach event handler things
-       *       update: we should switch away from the 'play' thing. And just call it 'call'
-       *               then each individial script can decide if he wants to attach himself to the frame update
-       *               or cutscene updates etc...
-       */
-
-      if( !_skaterift_script_already_viewed( k_escript_script_id_ch1s2 ) )
-      {
-         _skaterift_script_hook_apply_action( k_escript_script_id_ch1s2, k_script_action_play );
-         return 0;
-      }
-      else
-      {
-         return 1;
-      }
-   }
-
-   return 0;
-}
+   "start",
+   "volc",
+   "volc:tutorial",
+   "volc:leaving",
+
+   "mz",
+   /* NOTES: we need to block the player in to force them to talk to mike so they don't get lost? Or at least put 
+    *        mike right in the way of where you gotta go. Perhaps on the docks.
+    */
+
+   "mz:town_region",
+   "mz:battery_jump",
+   "mz:leaving_pt1",
+   "mz:start_pt2",
+   "mz:megapark_region",
+   "mz:leaving_pt2",
+
+   "city",
+   "city:main_region",
+   "city:finale",
+   "city:leaving",
+
+   "valley",
+   "valley:main_region",
+   "valley:rocket_inspection",
+   "valley:cave",
+   "valley:finale",
+   "valley:leaving",
+
+   NULL
+};
 
-static bool _skaterift_script_ch4s1a( enum escript_event ev, const char *inf )
+struct script_save_atom
 {
-   static u32 state, subtitle_id;
-   static struct cs_instance *override_inst;
-
-   if( ev == k_escript_event_call )
-   {
-      state = k_escript_state_loading;
-      override_inst = NULL;
-      subtitle_id = 0;
-      vg_info( "test:state = loading\n" );
-   }
-
-   if( ev == k_escript_event_cutscene_marker )
-   {
-      struct sr_subtitle EN[] = {
-      { "m1",  KCOL_MIKE "This has gotta be some kindof dream right?" },
-      { "m2",  KCOL_MIKE "I mean... Cambodia?" },
-      { "m3",  KCOL_MIKE "What are we even doing here.?" },
-      { NULL, NULL },
-      };
-      _skaterift_dialogue( EN, &subtitle_id, inf );
-
-      return 0;
-   }
-
-   /* scene 
-    * ---------------------------------------------------------------  */
-
-   if( state == k_escript_state_loading )
-   {
-      if( cmd_cutscene_load( 1, (const char *[]){ "metascenes/ch4s1a.ms" } ) )
-      {
-         state = k_escript_state_initializing;
-         vg_info( "test:state = initializing\n" );
-      }
-   }
-
-   if( state == k_escript_state_initializing )
-   {
-      if( _cutscene.state == k_cutscene_state_ready )
-      {
-         _skaterift_script_bind_player();
-         state = k_escript_state_playing;
-         vg_info( "test:state = playing\n" );
-         _cutscene_play();
-      }
-   }
+   const char *alias;
 
-   if( state == k_escript_state_playing )
+   enum save_atom_type
    {
-      if( _cutscene.state == k_cutscene_state_done )
-      {
-         state = k_escript_state_end;
-         vg_info( "test:state = end\n" );
-         _cutscene_unload();
-         return 1;
-      }
+      k_atom_type_numeric,
+      k_atom_type_enum
    }
-
-   return 0;
+   type;
+   
+   const char **enum_values;
+   u64 status;
 }
-
-
-static bool _skaterift_script_ch4s1( enum escript_event ev, const char *inf )
+_skaterift_script_savedata[] = 
 {
-   static u32 state, subtitle_id;
-   static struct cs_instance *override_inst;
-
-   if( ev == k_escript_event_call )
-   {
-      state = k_escript_state_loading;
-      override_inst = NULL;
-      subtitle_id = 0;
-      vg_info( "test:state = loading\n" );
-   }
-
-   if( ev == k_escript_event_cutscene_marker )
-   {
-      struct sr_subtitle EN[] = {
-      { "m1",  KCOL_MIKE "John hasn't turned up anywhere.." },
-      { "m2",  KCOL_MIKE "Not here, not back in Australia" },
-      { "m3",  KCOL_MIKE "nowhere?" },
-      { "m4",  KCOL_MIKE "I don't know how we can trust a single note.." },
-      { "m5",  KCOL_MIKE "I mean it is JC but.." },
-      { "m6",  KCOL_MIKE "Come on." },
-      { "m7",  KCOL_MIKE "I havn't seen him in weeks" },
-      { "m8",  KCOL_MIKE "I'm gonna go home," },
-      { "m9",  KCOL_MIKE "I'm bailing on this one man I'm sorry." },
-      { NULL, NULL },
-      };
-      _skaterift_dialogue( EN, &subtitle_id, inf );
+   { "story", k_atom_type_enum, _script_linear_story },
 
-      return 0;
-   }
-
-   /* scene 
-    * ---------------------------------------------------------------  */
-
-   if( state == k_escript_state_loading )
-   {
-      if( cmd_cutscene_load( 1, (const char *[]){ "metascenes/ch4s1.ms" } ) )
-      {
-         state = k_escript_state_initializing;
-         vg_info( "test:state = initializing\n" );
-      }
-   }
+   { "unlock_valley_view" },
+   { "unlock_mtzero_view" },
+   { "unlock_city_view" },
 
-   if( state == k_escript_state_initializing )
-   {
-      if( _cutscene.state == k_cutscene_state_ready )
-      {
-         _skaterift_script_bind_player();
-         state = k_escript_state_playing;
-         vg_info( "test:state = playing\n" );
-         _cutscene_play();
-      }
-   }
+   { "board_maker_unlock" },
+   { "board_maker_hub_view" },
 
-   if( state == k_escript_state_playing )
-   {
-      if( _cutscene.state == k_cutscene_state_done )
-      {
-         state = k_escript_state_end;
-         vg_info( "test:state = end\n" );
-         _cutscene_unload();
-         return 1;
-      }
-   }
+   { "ch1s3_view" },
+   { "ch1s3b_view" },
+   { "ch1s5_view" },
 
-   return 0;
-}
+#if 0
+   { "board_maker_unlock" },
+   { "board_maker_hub_view" },
+   { "intro_view" },
+   { "hub_info_view" },
 
-static bool _skaterift_script_ch4s2( enum escript_event ev, const char *inf )
-{
-   static u32 state, subtitle_id;
-   static struct cs_instance *override_inst;
+   { "ch1s2_view" },
+   { "ch1s3_view" },
+   { "ch1s3b_view" },
+   { "ch1s4_view" },
+   { "ch1s5_view" },
+   { "ch1s6a_view" },
+   { "unlock_docks_view" },
 
-   if( ev == k_escript_event_call )
-   {
-      state = k_escript_state_loading;
-      override_inst = NULL;
-      subtitle_id = 0;
-      vg_info( "test:state = loading\n" );
-   }
+   { "unlock_mtzero" },
+   { "ch2s1_view" },
+   { "ch2s2_view" },
+   { "ch2s3_view" },
+   { "battery_jump_view" },
+   { "ch2s4_view" },
+   { "ch2s5_view" },  /* is the trigger for the second map */
+   { "ch2s6_view" },
+   { "ch2e1_view" },
 
-   if( ev == k_escript_event_cutscene_marker )
-   {
-      struct sr_subtitle EN[] = {
-      { "m1",  KCOL_MIKE "What the hell is that thing?" },
-      { "f1",  KCOL_FBI  "Look man, all they told is that uhh" },
-      { "f2",  KCOL_FBI  "they're sending you up to one of saturns moons.." },
-      { "f3",  KCOL_FBI  "On that thing." },
-      { "f4",  KCOL_FBI  "To help you on your mission." },
-      { "f5",  KCOL_FBI  "You guys are more important than any person on earth right now" },
-      { "f6",  KCOL_FBI  "According to the president." },
-      { "f7",  KCOL_FBI  "But obviously this is some kind of joke I'm not in on." },
-      { "f8",  KCOL_FBI  "I don't believe a word of it." },
-      { NULL, NULL },
-      };
-      _skaterift_dialogue( EN, &subtitle_id, inf );
+   { "unlock_city" },
+   { "unlock_city_view" },
+   { "ch3s1_view" },
+   { "ch3s2_view" },
+   { "ch3s3_view" },
+   { "city_finale" },
 
-      return 0;
-   }
+   { "unlock_valley" },
 
-   /* scene 
-    * ---------------------------------------------------------------  */
+   { "valley_progress" },
 
-   if( state == k_escript_state_loading )
-   {
-      if( cmd_cutscene_load( 1, (const char *[]){ "metascenes/ch4s2.ms" } ) )
-      {
-         state = k_escript_state_initializing;
-         vg_info( "test:state = initializing\n" );
-      }
-   }
+   { "ch4s1a_view" },
+   { "ch4s2_view" },
+   { "valley_cave" },
+   { "ch4s1_view" },
+   { "valley_finale" },
+   { "ch4s3_view" },
+   { "rocket_launch_view" },
 
-   if( state == k_escript_state_initializing )
-   {
-      if( _cutscene.state == k_cutscene_state_ready )
-      {
-         _skaterift_script_bind_player();
-         state = k_escript_state_playing;
-         vg_info( "test:state = playing\n" );
-         _cutscene_play();
-      }
-   }
+   { "unlock_venus" },
+#endif
+};
 
-   if( state == k_escript_state_playing )
+struct script_save_atom *_skaterift_get_atom( const char *alias )
+{
+   for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
    {
-      if( _cutscene.state == k_cutscene_state_done )
-      {
-         state = k_escript_state_end;
-         vg_info( "test:state = end\n" );
-         _cutscene_unload();
-         return 1;
-      }
+      struct script_save_atom *atom = &_skaterift_script_savedata[i];
+      if( !strcmp( alias, atom->alias ) )
+         return atom;
    }
-
-   return 0;
+   return NULL;
 }
 
-static bool _skaterift_script_ch4s3( enum escript_event ev, const char *inf )
+u64 _skaterift_atom_enum_index( const char *atom_alias, const char *value, u64 fallback_value )
 {
-   static u32 state, subtitle_id;
-   static struct cs_instance *override_inst;
-
-   if( ev == k_escript_event_call )
-   {
-      state = k_escript_state_loading;
-      override_inst = NULL;
-      subtitle_id = 0;
-      vg_info( "test:state = loading\n" );
-   }
-
-   if( ev == k_escript_event_cutscene_marker )
+   struct script_save_atom *atom = _skaterift_get_atom( atom_alias );
+   if( !atom )
    {
-      struct sr_subtitle EN[] = {
-      { "j1", KCOL_JOHN "Betcha didn't think ya'd see me here!!?" },
-      { "j2", KCOL_JOHN "Did you miss me?" },
-      { "j3", KCOL_JOHN "You're probably wondering how the hell I got up here myself right?" },
-      { "j4", KCOL_JOHN "Well. I'm not gonna tell you." },
-      { "j5", KCOL_JOHN "It was all a trick. A ROUSE!" },
-      { "j6", KCOL_JOHN "Truth is, none of this is really real!" },
-      { "j7", KCOL_JOHN "And I'm leaving you here." },
-      { "j8", KCOL_JOHN "Cause its the only way I'm gonna get you to wake up." },
-      { "j9", KCOL_JOHN "Sorry I had to do all this to you..." },
-      { "j10",KCOL_JOHN "We can still be friends right?" },
-      { NULL, NULL },
-      };
-      _skaterift_dialogue( EN, &subtitle_id, inf );
-
+      vg_error( "No atom aliased '%s'\n", atom_alias );
       return 0;
    }
 
-   /* scene 
-    * ---------------------------------------------------------------  */
-
-   if( state == k_escript_state_loading )
-   {
-      if( cmd_cutscene_load( 1, (const char *[]){ "metascenes/ch4s3.ms" } ) )
-      {
-         state = k_escript_state_initializing;
-         vg_info( "test:state = initializing\n" );
-      }
-   }
-
-   if( state == k_escript_state_initializing )
+   VG_ASSERT( atom->type == k_atom_type_enum );
+   if( value )
    {
-      if( _cutscene.state == k_cutscene_state_ready )
+      for( u32 i=0; i<32; i ++ )
       {
-         _skaterift_script_bind_player();
-         state = k_escript_state_playing;
-         vg_info( "test:state = playing\n" );
-         _cutscene_play();
-      }
-   }
-
-   if( state == k_escript_state_playing )
-   {
-      if( _cutscene.state == k_cutscene_state_done )
-      {
-         state = k_escript_state_end;
-         vg_info( "test:state = end\n" );
-         _cutscene_unload();
-         return 1;
+         if( !atom->enum_values[i] )
+         {
+            vg_warn( "Atom '%s' does't contain the value '%s'\n", atom->alias, value );
+            return fallback_value;
+         }
+         if( !strcmp( atom->enum_values[i], value ) )
+            return i;
       }
+      vg_warn( "Atom '%s' exceeds max enum values (%u)\n", atom->alias, 32 );
    }
-
-   return 0;
+   return fallback_value;
 }
 
-
-/* This is the development one */
-static bool _skaterift_script_test( enum escript_event ev, const char *inf )
+u64 _skaterift_atom_status( const char *atom_alias )
 {
-   static u32 state;
-   static m4x3f *action_cam;
-   static bool action_mode;
-   static u32 subtitle_id;
-
-   if( ev == k_escript_event_call )
+   struct script_save_atom *atom = _skaterift_get_atom( atom_alias );
+   if( !atom )
    {
-      state = k_escript_state_loading;
-      action_cam = NULL;
-      action_mode = 0;
-      subtitle_id = 0;
-      vg_info( "test:state = loading\n" );
-   }
-
-   if( ev == k_escript_event_cutscene_marker )
-   {
-      if( vg_str_eq( inf, "action_cam" ) )
-         action_mode = 1;
-
-      struct sr_subtitle EN[] = {
-      { "john_line_0", KCOL_JOHN "Mike mike mike, I need you to get over here now" },
-      { "mike_line_0", KCOL_MIKE "What is it now JC?" },
-      { "john_line_1", KCOL_JOHN "Well we were out here, shooting this massive gap right?" },
-      { "john_line_1a",KCOL_JOHN "It was gonna be the perfect shot, and it was going so good" },
-      { "john_line_2", KCOL_JOHN "Intro was perfect, got the perfect frame, angles lighting. PERFECT" },
-      { "mike_line_1", KCOL_MIKE "Whatever mate, what happened?" },
-      { "john_line_3", KCOL_JOHN "Uh yeah yeah, we were about 10 floors up right?" },
-      { "john_line_3a",KCOL_JOHN "Yeah uhhh, they didn't make the gap." },
-      { "john_line_4", KCOL_JOHN "And im im freaking out here man, it was worst case" },
-      { "john_line_4a",KCOL_JOHN "I mean.. WORST CASE" },
-      { "mike_line_2", KCOL_MIKE "yeaahkay, what are you doing calling me instead of an ambo?" },
-      { "john_line_5", KCOL_JOHN "I thought you could help us!" },
-      { "mike_line_3", KCOL_MIKE "Hang up, and call tripple zero mate" },
-      { "mike_line_3a",KCOL_MIKE "Did you even check if they were okay?" },
-      { "john_line_6", KCOL_JOHN "Holy crap, you're still alive!" },
-      { "john_line_6a",KCOL_JOHN "Nevermind Mike, cheers" },
-      { "john_line_7", KCOL_JOHN "Lets get out of here mate." },
-      { NULL, NULL },
-      };
-      _skaterift_dialogue( EN, &subtitle_id, inf );
+      vg_error( "No atom aliased '%s'\n", atom_alias );
       return 0;
    }
+   else return atom->status;
+}
 
-   /* scene 
-    * ---------------------------------------------------------------  */
-
-   if( state == k_escript_state_loading )
+void _skaterift_atom_set( const char *atom_alias, u64 value )
+{
+   struct script_save_atom *atom = _skaterift_get_atom( atom_alias );
+   if( !atom )
    {
-      if( cmd_cutscene_load( 1, (const char *[]){ "metascenes/test_scene.ms" } ) )
-      {
-         state = k_escript_state_initializing;
-         vg_info( "test:state = initializing\n" );
-      }
+      vg_error( "No atom aliased '%s'\n", atom_alias );
+      return;
    }
 
-   if( state == k_escript_state_initializing )
-   {
-      if( _cutscene.state == k_cutscene_state_ready )
-      {
-         _skaterift_script_bind_player();
-
-         struct cs_instance *boogie_inst = 
-            _cutscene_get_first_model_instance( "models/boogie_van" );
-
-         if( boogie_inst )
-         {
-            struct model_ref *mref = &_cutscene.refs[ boogie_inst->ref_id ];
-            struct skeleton *sk = &mref->skeletons[0].sk;
-
-            for( u32 i=0; i<sk->bone_count; i ++ )
-            {
-               vg_info( "%s\n", sk->bones[i].name );
-               if( !strcmp( sk->bones[i].name, "action_cam" ) )
-               {
-                  action_cam = boogie_inst->skinning_data + i;
-                  break;
-               }
-            }
+   atom->status = value;
 
-            if( action_cam == NULL )
-            {
-               vg_error( "test: Failed to find action cam bone" );
-               return 1;
-            }
-         }
-         else
-         {
-            vg_error( "test: Failed to find boogie van" );
-            return 1;
-         }
+   struct script_event_atom_changed info;
+   info.alias = atom_alias;
+   info.value = value;
+   struct ent_script_event event;
+   event.type = k_escript_event_atom_changed;
+   event.info = &info;
+   ent_script_propogate_event( &_world.main, &event );
+}
 
-         state = k_escript_state_playing;
-         vg_info( "test:state = playing\n" );
-         _cutscene_play();
-      }
-   }
+void _skaterift_atom_set_enum( const char *atom_alias, const char *value )
+{
+   _skaterift_atom_set( atom_alias, _skaterift_atom_enum_index( atom_alias, value, 0 ) );
+}
 
-   if( state == k_escript_state_playing )
+void _skaterift_script_write_savedata( vg_msg *sav )
+{
+   for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
    {
-      if( _cutscene.state == k_cutscene_state_done )
-      {
-         state = k_escript_state_end;
-         vg_info( "test:state = end\n" );
-         _cutscene_unload();
-         return 1;
-      }
+      struct script_save_atom *atom = &_skaterift_script_savedata[i];
+      if( atom->type == k_atom_type_numeric )
+         vg_msg_wkvnum( sav, atom->alias, k_vg_msg_u64, 1, &atom->status );
       else
-      {
-         if( action_mode )
-            _TEMP_VAR = action_cam;
-      }
+         vg_msg_wkvstr( sav, atom->alias, atom->enum_values[ atom->status ] );
    }
-
-   return 0;
 }
 
-#endif
-
-
-extern m4x3f *_TEMP_VAR;
-
-#if 0
-enum generic_cutscene_event generic_cutscene_wrapper( const struct generic_cutscene *cutscene_template, 
-                                                      ent_script_event *event )
+void _skaterift_script_load_savedata( vg_msg *sav )
 {
-   if( event->type == k_escript_event_allocate )
-   {
-      struct script_event_allocate *event_info = event->info;
-      struct generic_cutscene *generic = vg_linear_alloc( event_info->heap, sizeof(struct generic_cutscene) );
-      memcpy( generic, cutscene_template, sizeof(struct generic_cutscene) );
-      event_info->userdata = generic;
-      return k_generic_cutscene_event_none;
-   }
-   else
+   for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
    {
-      struct generic_cutscene *generic = event->userdata;
-
-      if( event->type == k_escript_event_update )
-      {
-         if( generic->state == k_generic_cutscene_state_wake )
-         {
-            if( _cutscene.state == k_cutscene_state_none )
-            {
-               if( cmd_cutscene_load( 1, (const char *[]){ generic->metascene_path } ) )
-               {
-                  generic->state = k_generic_cutscene_state_init;
-                  vg_info( "generic_cutscene:state = initializing\n" );
-               }
-            }
-
-            if( generic->trigger_start == 0 )
-            {
-               generic->trigger_start = 1;
-               return k_generic_cutscene_event_start;
-            }
-            else
-               return k_generic_cutscene_event_none;
-         }
-
-         if( generic->state == k_generic_cutscene_state_init )
-         {
-            if( _cutscene.state == k_cutscene_state_ready )
-            {
-               if( generic->subtitles )
-               {
-                  _cutscene_set_subtitle_list( generic->subtitles );
-               }
-
-               _skaterift_script_bind_player();
-               _cutscene_play();
-               generic->state = k_generic_cutscene_state_playing;
-               vg_info( "generic_template:state = playing\n" );
-               return k_generic_cutscene_event_start;
-            }
-         }
-
-         if( generic->state == k_generic_cutscene_state_playing )
-         {
-            if( _cutscene.state == k_cutscene_state_done )
-            {
-               generic->state = k_generic_cutscene_state_end;
-
-               vg_info( "generic_template:state = end\n" );
-               _cutscene_unload();
-
-
-               return k_generic_cutscene_event_end;
-            }
-         }
-
-         return k_generic_cutscene_event_none;
-      }
+      struct script_save_atom *atom = &_skaterift_script_savedata[i];
+      if( atom->type == k_atom_type_numeric )
+         vg_msg_getkvintg( sav, atom->alias, k_vg_msg_u64, &atom->status, NULL );
       else
-         return k_generic_cutscene_event_none;
+         atom->status = _skaterift_atom_enum_index( atom->alias, vg_msg_getkvstr( sav, atom->alias ), 0 );
    }
 }
 
-void play_generic_cutscene( ent_script_event *event )
-{
-   struct generic_cutscene *generic = event->userdata;
-   generic->state = k_generic_cutscene_state_wake;
-}
-#endif
+/* script events 
+ * ------------------------------------------------------------------------------------------------------------- */
 
 bool on_cutscene_marker( ent_script_event *event, const char *marker )
 {
    if( event->type != k_escript_event_allocate )
+   {
       if( _cutscene.state == k_cutscene_state_playing )
+      {
          if( _cutscene.marker_this_frame )
+         {
             if( vg_str_eq( marker, _cutscene.marker_this_frame ) )
                return 1;
-
+         }
+      }
+   }
    return 0;
 }
 
-bool on_nugget_changed( ent_script_event *event, const char *nugget_alias, u64 *out_value )
+bool on_world_start( ent_script_event *event )
+{
+   return event->type == k_escript_event_world_start;
+}
+
+bool on_atom_changed( ent_script_event *event, const char *atom_alias, u64 *out_value )
 {
-   if( event->type == k_escript_event_nugget_changed )
+   if( event->type == k_escript_event_atom_changed )
    {
-      struct script_event_nugget_changed *nugget_info = event->info;
-      if( !strcmp( nugget_alias, nugget_info->alias ) )
+      struct script_event_atom_changed *atom_info = event->info;
+      if( !strcmp( atom_alias, atom_info->alias ) )
       {
-         *out_value = nugget_info->value;
+         *out_value = atom_info->value;
          return 1;
       }
    }
    else if( event->type == k_escript_event_world_start )
    {
-      *out_value = _skaterift_script_nugget_status( nugget_alias );
+      *out_value = _skaterift_atom_status( atom_alias );
       return 1;
    }
 
    return 0;
 }
 
+#if 0
 bool on_function_trigger( ent_script_event *event, i32 function_id )
 {
    if( event->type == k_escript_event_call )
    {
       struct script_event_call *call_info = event->info;
       if( call_info->function_id == function_id )
-      {
          return 1;
-      }
    }
 
    return 0;
 }
 
-bool on_nugget_once( ent_script_event *event, const char *nugget_alias )
+bool on_atom_once( ent_script_event *event, const char *atom_alias )
 {
    if( event->type != k_escript_event_allocate )
    {
-      if( _skaterift_script_nugget_status( nugget_alias ) != 1 )
+      if( _skaterift_atom_status( atom_alias ) != 1 )
       {
-         _skaterift_script_nugget_set( nugget_alias, 1 );
+         _skaterift_atom_set( atom_alias, 1 );
          return 1;
       }
    }
@@ -577,53 +285,18 @@ bool on_nugget_once( ent_script_event *event, const char *nugget_alias )
    return 0;
 }
 
-bool on_completion_changed( ent_script_event *event )
+bool on_advancement( ent_script_event *event )
 {
    if( event->type == k_escript_event_completion_changed )
+      return 1; 
+   if( event->type == k_escript_event_world_start) 
       return 1;
-   return 0;
-}
-
-#if 0
-enum generic_cutscene_event optional_video_wrapper( const struct generic_cutscene *cutscene_template, 
-                                                    const char *nugget_alias,
-                                                    u64 nugget_visible_value,
-                                                    ent_script_event *event )
-{
-   enum generic_cutscene_event cs_event = generic_cutscene_wrapper( cutscene_template, event );
-
-   u64 status;
-   if( on_nugget_changed( event, nugget_alias, &status ) )
-   {
-      ent_list_set_visible( event->world, event->entity_list, status == nugget_visible_value );
-   }
-
-   if( on_function_trigger( event, 0 ) )
-   {
-      if( on_nugget_once( event, nugget_alias ) )
-      {
-         play_generic_cutscene( event );
-      }
-   }
-
-   return cs_event;
-}
-
-enum generic_cutscene_event challenge_video_wrapper( const struct generic_cutscene *cutscene_template, 
-                                                     const char *nugget_alias,
-                                                     ent_script_event *event )
-{
-   enum generic_cutscene_event cs_event = generic_cutscene_wrapper( cutscene_template, event );
 
-   if( on_function_trigger( event, 0 ) )
-   {
-      if( on_nugget_once( event, nugget_alias ) )
-      {
-         play_generic_cutscene( event );
-      }
-   }
+   u64 _0;
+   if( on_atom_changed( event, "story", &_0 ) )
+      return 1;
 
-   return cs_event;
+   return 0;
 }
 #endif
 
@@ -635,6 +308,37 @@ enum generic_cutscene_event challenge_video_wrapper( const struct generic_cutsce
 #include "scripts/tutorial_island.c"
 #include "scripts/mtzero.c"
 #include "scripts/city.c"
+#include "scripts/valley.c"
+
+#include "scripts/cutscene.c"
+#include "scripts/explode.c"
+
+static bool _skaterift_atom_script( ent_script_event *event )
+{
+   if( event->type == k_escript_event_world_event )
+   {
+      struct script_event_world_io *inf = event->info;
+      world_instance *world = &_world.main;
+
+           if( AF_STR_EQ( &world->meta.af, inf->event->pstr_recieve_event, "pass_once" ) )
+      {
+         // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
+         if( inf->event->flags & k_ent_event_data_const_string )
+         {
+            const char *alias = af_str( &world->meta.af, inf->event->data.const_pstr );
+            if( _skaterift_atom_status( alias ) != 1 )
+            {
+               _skaterift_atom_set( alias, 1 );
+               _world_raise_event( inf->event->recieve_entity_id, "pass" );
+            }
+            else 
+               _world_raise_event( inf->event->recieve_entity_id, "fail" );
+         }
+      }
+   }
+   
+   return 1;
+}
 
 /* --------------------------------------------------------------------------------------------------------------------
  *   function aliasing
@@ -642,11 +346,15 @@ enum generic_cutscene_event challenge_video_wrapper( const struct generic_cutsce
 
 struct ent_script_table_entry _ent_script_table[] =
 {
+   { "cutscene", _skaterift_script_cutscene },
+   { "explode", _skaterift_script_explode },
+   { "atom", _skaterift_atom_script },
+#if 0
+   { "hub", _skaterift_script_hub },
    { "board_maker_unlock", _skaterift_script_board_maker_unlock },
    { "board_maker", _skaterift_script_board_maker },
 
    //{ "intro", _skaterift_script_intro },
-   { "hub", _skaterift_script_hub },
 
    { "tutorial_island", _skaterift_script_tutorial_island },
    { "ch1s3", _skaterift_script_ch1s3 },
@@ -668,112 +376,17 @@ struct ent_script_table_entry _ent_script_table[] =
    { "ch3s2", _skaterift_script_ch3s2 },
    { "ch3s3", _skaterift_script_ch3s3 },
 
-   { NULL }
-};
-
-/* --------------------------------------------------------------------------------------------------------------------
- *   save data
- */
-
-struct script_save_nugget
-{
-   const char *alias;
-   u64 status;
-}
-_skaterift_script_savedata[] = 
-{
-   { "board_maker_unlock" },
-   { "board_maker_hub_view" },
-   { "intro_view" },
-   { "hub_info_view" },
-
-   { "ch1s2_view" },
-   { "ch1s3_view" },
-   { "ch1s3b_view" },
-   { "ch1s4_view" },
-   { "ch1s5_view" },
-   { "ch1s6a_view" },
-   { "unlock_docks_view" },
-
-   { "unlock_mtzero" },
-   { "unlock_mtzero_view" },
-   { "ch2s1_view" },
-   { "ch2s2_view" },
-   { "ch2s3_view" },
-   { "battery_jump_view" },
-   { "ch2s4_view" },
-   { "ch2s5_view" },  /* is the trigger for the second map */
-   { "ch2s6_view" },
-   { "ch2e1_view" },
-
-   { "unlock_city" },
-   { "unlock_city_view" },
-   { "ch3s1_view" },
-   { "ch3s2_view" },
-   { "ch3s3_view" },
-   { "city_finale" },
-
-   { "unlock_valley" },
-   { "unlock_valley_view" },
+   { "valley", _skaterift_script_valley },
+   { "ch4s2", _skaterift_script_ch4s2 },
+   { "ch4s1", _skaterift_script_ch4s1 },
+#endif
 
-   { "unlock_venus" },
+   { NULL }
 };
 
-u64 _skaterift_script_nugget_status( const char *nugget_alias )
-{
-   for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
-   {
-      struct script_save_nugget *nugget = &_skaterift_script_savedata[i];
-      if( !strcmp( nugget_alias, nugget->alias ) )
-         return nugget->status;
-   }
-
-   vg_error( "No nugget named: '%s'\n", nugget_alias );
-   return 0;
-}
-
-void _skaterift_script_nugget_set( const char *nugget_alias, u64 value )
-{
-   for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
-   {
-      struct script_save_nugget *nugget = &_skaterift_script_savedata[i];
-      if( !strcmp( nugget_alias, nugget->alias ) )
-      {
-         nugget->status = value;
-
-         struct script_event_nugget_changed info;
-         info.alias = nugget_alias;
-         info.value = value;
-
-         struct ent_script_event event;
-         event.type = k_escript_event_nugget_changed;
-         event.info = &info;
-
-         ent_script_propogate_event( &_world.main, &event );
-         return;
-      }
-   }
 
-   vg_error( "No nugget named: '%s'\n", nugget_alias );
-}
-
-void _skaterift_script_write_savedata( vg_msg *sav )
-{
-   for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
-   {
-      struct script_save_nugget *nugget = &_skaterift_script_savedata[i];
-      vg_msg_wkvnum( sav, nugget->alias, k_vg_msg_u64, 1, &nugget->status );
-   }
-}
-
-void _skaterift_script_load_savedata( vg_msg *sav )
-{
-   for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
-   {
-      struct script_save_nugget *nugget = &_skaterift_script_savedata[i];
-      vg_msg_getkvintg( sav, nugget->alias, k_vg_msg_u64, &nugget->status, NULL );
-   }
-}
+/* console eventts
+ * ------------------------------------------------------------------------------------------------------------- */
 
 static int _skaterift_script_ccmd( int argc, const char *argv[] )
 {
@@ -783,7 +396,7 @@ static int _skaterift_script_ccmd( int argc, const char *argv[] )
       return 0;
    }
 
-   if( !strcmp( argv[0], "nugget" ) ) 
+   if( !strcmp( argv[0], "atom" ) ) 
    {
       bool all = 0;
       if( !strcmp( argv[1], "all" ) ) 
@@ -791,11 +404,25 @@ static int _skaterift_script_ccmd( int argc, const char *argv[] )
 
       for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
       {
-         struct script_save_nugget *nugget = &_skaterift_script_savedata[i];
-         if( all || !strcmp( argv[1], nugget->alias ) )
+         struct script_save_atom *atom = &_skaterift_script_savedata[i];
+         if( all || !strcmp( argv[1], atom->alias ) )
          {
-            if( argc==3 ) _skaterift_script_nugget_set( nugget->alias, atol(argv[2]) );
-            else vg_info( "%s: %lu\n", nugget->alias, nugget->status );
+            if( argc==3 ) 
+            {
+               u64 value = 0;
+               if( atom->type == k_atom_type_numeric )
+                  value = atol(argv[2]);
+               else
+                  value = _skaterift_atom_enum_index( atom->alias, argv[2], atom->status );
+               _skaterift_atom_set( atom->alias, value );
+            }
+            else 
+            {
+               if( atom->type == k_atom_type_numeric )
+                  vg_info( "%s: %lu\n", atom->alias, atom->status );
+               else
+                  vg_info( "%s: '%s' (%lu)\n", atom->alias, atom->enum_values[ atom->status ], atom->status );
+            }
          }
       }
 
@@ -827,18 +454,18 @@ static void _skaterift_script_ccmd_poll( int argc, const char *argv[] )
 
    if( argc == 1 )
    {
-      console_suggest_score_text( "nugget", term, 0 );
+      console_suggest_score_text( "atom", term, 0 );
       console_suggest_score_text( "trigger", term, 0 );
    }
    else if( argc == 2 )
    {
-      if( !strcmp( argv[0], "nugget" ) )
+      if( !strcmp( argv[0], "atom" ) )
       {
          console_suggest_score_text( "all", term, 0 );
          for( u32 i=0; i<VG_ARRAY_LEN( _skaterift_script_savedata ); i ++ )
          {
-            struct script_save_nugget *nugget = &_skaterift_script_savedata[i];
-            console_suggest_score_text( nugget->alias, term, 0 );
+            struct script_save_atom *atom = &_skaterift_script_savedata[i];
+            console_suggest_score_text( atom->alias, term, 0 );
          }
       }
       else if( !strcmp( argv[0], "trigger" ) )
@@ -846,6 +473,25 @@ static void _skaterift_script_ccmd_poll( int argc, const char *argv[] )
          console_suggest_score_text( "start", term, 0 );
       }
    }
+   else if( argc == 3 )
+   {
+      if( !strcmp( argv[0], "atom" ) )
+      {
+         if( strcmp( argv[1], "all" ) )
+         {
+            struct script_save_atom *atom = _skaterift_get_atom( argv[1] );
+            if( atom->type == k_atom_type_enum )
+            {
+               for( u32 i=0; i<32; i ++ )
+               {
+                  if( !atom->enum_values[i] )
+                     break;
+                  console_suggest_score_text( atom->enum_values[i], term, 0 );
+               }
+            }
+         }
+      }
+   }
 }
 
 void _skaterift_script_init(void)
index 8cbad900c0bfa0f0e3f9507f9e43741b399a0579..2cb58f9756b3dff09a5f8b08f659459307c97026 100644 (file)
@@ -1,39 +1,19 @@
 #pragma once
 #include "ent_script.h"
+#define ATOM_MAX 0xfffffffffffffffflu
 
 void _skaterift_script_init(void);
 void _skaterift_script_write_savedata( vg_msg *sav );
 void _skaterift_script_load_savedata( vg_msg *sav );
 
-u64 _skaterift_script_nugget_status( const char *nugget_alias );
-void _skaterift_script_nugget_set( const char *nugget_alias, u64 value );
+u64 _skaterift_atom_status( const char *atom_alias );
+u64 _skaterift_atom_enum_index( const char *atom_alias, const char *value, u64 fallback_value );
+void _skaterift_atom_set( const char *atom_alias, u64 value );
+void _skaterift_atom_set_enum( const char *atom_alias, const char *value );
 
-#if 0
-struct generic_cutscene
-{
-   enum generic_cutscene_state
-   {
-      k_generic_cutscene_state_none,
-      k_generic_cutscene_state_wake,
-      k_generic_cutscene_state_init,
-      k_generic_cutscene_state_loading,
-      k_generic_cutscene_state_playing,
-      k_generic_cutscene_state_end
-   }
-   state;
-   const char *metascene_path;
-   const cs_subtitle *subtitles;
-   bool freeze_player;
-   bool trigger_start;
-};
-
-enum generic_cutscene_event
-{
-   k_generic_cutscene_event_none,
-   k_generic_cutscene_event_end,
-   k_generic_cutscene_event_start
-};
-
-enum generic_cutscene_event generic_cutscene_wrapper( const struct generic_cutscene *cutscene_template, ent_script_event *event );
-void play_generic_cutscene( ent_script_event *event );
-#endif
+bool on_world_start( ent_script_event *event );
+bool on_atom_changed( ent_script_event *event, const char *atom_alias, u64 *out_value );
+bool on_cutscene_marker( ent_script_event *event, const char *marker );
+bool on_function_trigger( ent_script_event *event, i32 function_id );
+bool on_atom_once( ent_script_event *event, const char *atom_alias );
+bool on_advancement( ent_script_event *event );
index dc15a00bd11ddbf0e45df29f301e97e3cfe99794..74b31b2b33f672952ce454ef47f8e3c374f49e6a 100644 (file)
@@ -49,10 +49,9 @@ struct skeleton_anim
 
 static u32 skeleton_bone_id( struct skeleton *skele, const char *name )
 {
-   for( u32 i=1; i<skele->bone_count; i++ ){
+   for( u32 i=1; i<skele->bone_count; i++ )
       if( !strcmp( skele->bones[i].name, name ))
          return i;
-   }
 
    vg_error( "skeleton_bone_id( *, \"%s\" );\n", name );
    vg_fatal_error( "Bone does not exist\n" );
@@ -60,8 +59,7 @@ static u32 skeleton_bone_id( struct skeleton *skele, const char *name )
    return 0;
 }
 
-static void keyframe_copy_pose( ms_keyframe *kfa, ms_keyframe *kfb, 
-                                   int num )
+static void keyframe_copy_pose( ms_keyframe *kfa, ms_keyframe *kfb, int num )
 {
    for( int i=0; i<num; i++ )
       kfb[i] = kfa[i];
@@ -69,8 +67,7 @@ static void keyframe_copy_pose( ms_keyframe *kfa, ms_keyframe *kfb,
 
 
 /* apply a rotation from the perspective of root */
-static void keyframe_rotate_around( ms_keyframe *kf, 
-                                    v3f origin, v3f offset, v4f q )
+static void keyframe_rotate_around( ms_keyframe *kf, v3f origin, v3f offset, v4f q )
 {
    v3f v0, co;
    v3_add( kf->co, offset, co );
@@ -83,8 +80,8 @@ static void keyframe_rotate_around( ms_keyframe *kf,
    q_normalize( kf->q );
 }
 
-static void keyframe_lerp( ms_keyframe *kfa, ms_keyframe *kfb, f32 t,
-                           ms_keyframe *kfd ){
+static void keyframe_lerp( ms_keyframe *kfa, ms_keyframe *kfb, f32 t, ms_keyframe *kfd )
+{
    v3_lerp( kfa->co, kfb->co, t, kfd->co );
    q_nlerp( kfa->q,  kfb->q,  t, kfd->q );
    v3_lerp( kfa->s,  kfb->s,  t, kfd->s );
@@ -93,13 +90,15 @@ static void keyframe_lerp( ms_keyframe *kfa, ms_keyframe *kfb, f32 t,
 /*
  * Lerp between two sets of keyframes and store in dest. Rotations use Nlerp.
  */
-static void keyframe_lerp_pose( ms_keyframe *kfa, ms_keyframe *kfb, 
-                                float t, ms_keyframe *kfd, int count ){
-   if( t <= 0.0001f ){
+static void keyframe_lerp_pose( ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd, int count )
+{
+   if( t <= 0.0001f )
+   {
       keyframe_copy_pose( kfa, kfd, count );
       return;
    }
-   else if( t >= 0.9999f ){
+   else if( t >= 0.9999f )
+   {
       keyframe_copy_pose( kfb, kfd, count );
       return;
    }
@@ -108,16 +107,12 @@ static void keyframe_lerp_pose( ms_keyframe *kfa, ms_keyframe *kfb,
       keyframe_lerp( kfa+i, kfb+i, t, kfd+i );
 }
 
-static 
-void skeleton_lerp_pose( struct skeleton *skele,
-                         ms_keyframe *kfa, ms_keyframe *kfb, float t,
-                         ms_keyframe *kfd )
+static void skeleton_lerp_pose( struct skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfb, float t, ms_keyframe *kfd )
 {
    keyframe_lerp_pose( kfa, kfb, t, kfd, skele->bone_count-1 );
 }
 
-static void skeleton_copy_pose( struct skeleton *skele,
-                                   ms_keyframe *kfa, ms_keyframe *kfd )
+static void skeleton_copy_pose( struct skeleton *skele, ms_keyframe *kfa, ms_keyframe *kfd )
 {
    keyframe_copy_pose( kfa, kfd, skele->bone_count-1 );
 }
@@ -128,34 +123,27 @@ static void skeleton_copy_pose( struct skeleton *skele,
  *
  * Time is in SECONDS
  */
-void skeleton_sample_anim( struct skeleton *skele,
-                           skeleton_anim *anim,
-                           float time,
-                           ms_keyframe *output )
+void skeleton_sample_anim( struct skeleton *skele, skeleton_anim *anim, f32 time, ms_keyframe *output )
 {
    ms_strip *strip = anim->strip;
-   f32 animtime  = fmodf( time*anim->framerate, (f32)strip->length ),
+   f32 animtime  = fmodf( time*anim->framerate, (f32)strip->strip.length ),
        animframe = floorf( animtime ),
        t = animtime - animframe;
 
+   u32 frame = (u32)animframe % strip->strip.length,
+       next  = (frame+1) % strip->strip.length;
 
-   u32 frame = (u32)animframe % strip->length,
-       next  = (frame+1) % strip->length;
-
-   ms_keyframe *base  = anim->keyframes_base + strip->data_count*frame,
-               *nbase = anim->keyframes_base + strip->data_count*next;
+   ms_keyframe *base  = anim->keyframes_base + strip->strip.count*frame,
+               *nbase = anim->keyframes_base + strip->strip.count*next;
 
    skeleton_lerp_pose( skele, base, nbase, t, output );
 }
 
 /* time is in SECONDS */
-int skeleton_sample_anim_clamped( struct skeleton *skele,
-                                  skeleton_anim *anim,
-                                  float time,
-                                  ms_keyframe *output )
+int skeleton_sample_anim_clamped( struct skeleton *skele, skeleton_anim *anim, f32 time, ms_keyframe *output )
 {
    ms_strip *strip = anim->strip;
-   f32 end = (strip->length-1)/anim->framerate;
+   f32 end = (strip->strip.length-1)/anim->framerate;
    skeleton_sample_anim( skele, anim, vg_minf( end, time ), output );
 
    if( time > end ) return 0;
@@ -171,25 +159,26 @@ typedef enum anim_apply
 }
 anim_apply;
 
-static 
-int should_apply_bone( struct skeleton *skele, u32 id, anim_apply type )
+static int should_apply_bone( struct skeleton *skele, u32 id, anim_apply type )
 {
    struct skeleton_bone *sb = &skele->bones[ id ],
                         *sp = &skele->bones[ sb->parent ];
 
-   if( type == k_anim_apply_defer_ik ){
-      if( ((sp->flags & k_bone_flag_ik) && !(sb->flags & k_bone_flag_ik)) 
-          || sp->defer )
+   if( type == k_anim_apply_defer_ik )
+   {
+      if( ((sp->flags & k_bone_flag_ik) && !(sb->flags & k_bone_flag_ik)) || sp->defer )
       {
          sb->defer = 1;
          return 0;
       }
-      else{
+      else
+      {
          sb->defer = 0;
          return 1;
       }
    }
-   else if( type == k_anim_apply_deffered_only ){
+   else if( type == k_anim_apply_deffered_only )
+   {
       if( sb->defer )
          return 1;
       else
@@ -202,8 +191,7 @@ int should_apply_bone( struct skeleton *skele, u32 id, anim_apply type )
 /*
  * Apply block of keyframes to skeletons final pose
  */
-static void skeleton_apply_pose( struct skeleton *skele, ms_keyframe *pose,
-                                 anim_apply passtype, m4x3f *final_mtx )
+static void skeleton_apply_pose( struct skeleton *skele, ms_keyframe *pose, anim_apply passtype, m4x3f *final_mtx )
 {
    if( passtype == k_anim_apply_absolute )
    {
@@ -228,7 +216,6 @@ static void skeleton_apply_pose( struct skeleton *skele, ms_keyframe *pose,
    {
       struct skeleton_bone *sb = &skele->bones[i],
                            *sp = &skele->bones[sb->parent];
-      
       if( !should_apply_bone( skele, i, passtype ) )
          continue;
 
@@ -255,10 +242,10 @@ static void skeleton_apply_pose( struct skeleton *skele, ms_keyframe *pose,
 /* 
  * Take the final matrices and decompose it into an absolute positioned anim
  */
-static void skeleton_decompose_mtx_absolute( struct skeleton *skele, 
-                                             ms_keyframe *anim,
-                                             m4x3f *final_mtx ){
-   for( u32 i=1; i<skele->bone_count; i++ ){
+static void skeleton_decompose_mtx_absolute( struct skeleton *skele, ms_keyframe *anim, m4x3f *final_mtx )
+{
+   for( u32 i=1; i<skele->bone_count; i++ )
+   {
       struct skeleton_bone *sb = &skele->bones[i];
       ms_keyframe *kf = &anim[i-1];
       m4x3_decompose( final_mtx[i], kf->co, kf->q, kf->s );
@@ -269,9 +256,7 @@ static void skeleton_decompose_mtx_absolute( struct skeleton *skele,
  * creates the reference inverse matrix for an IK bone, as it has an initial 
  * intrisic rotation based on the direction that the IK is setup..
  */
-static void skeleton_inverse_for_ik( struct skeleton *skele,
-                                     v3f ivaxis,
-                                     u32 id, m3x3f inverse )
+static void skeleton_inverse_for_ik( struct skeleton *skele, v3f ivaxis, u32 id, m3x3f inverse )
 {
    v3_copy( ivaxis, inverse[0] );
    v3_copy( skele->bones[id].end, inverse[1] );
@@ -286,9 +271,9 @@ static void skeleton_inverse_for_ik( struct skeleton *skele,
 static void skeleton_create_inverses( struct skeleton *skele )
 {
    /* IK: inverse 'plane-bone space' axis '(^axis,^bone,...)[base] */
-   for( u32 i=0; i<skele->ik_count; i++ ){
+   for( u32 i=0; i<skele->ik_count; i++ )
+   {
       struct skeleton_ik *ik = &skele->ik[i];
-
       m4x3f inverse;
       v3f iv0, iv1, ivaxis;
       v3_sub( skele->bones[ik->target].co, skele->bones[ik->lower].co, iv0 );
@@ -304,11 +289,10 @@ static void skeleton_create_inverses( struct skeleton *skele )
 /*
  * Apply a model matrix to all bones, should be done last
  */
-static 
-void skeleton_apply_transform( struct skeleton *skele, m4x3f transform,
-                               m4x3f *final_mtx )
+static void skeleton_apply_transform( struct skeleton *skele, m4x3f transform, m4x3f *final_mtx )
 {
-   for( u32 i=0; i<skele->bone_count; i++ ){
+   for( u32 i=0; i<skele->bone_count; i++ )
+   {
       struct skeleton_bone *sb = &skele->bones[i];
       m4x3_mul( transform, final_mtx[i], final_mtx[i] );
    }
@@ -318,13 +302,14 @@ void skeleton_apply_transform( struct skeleton *skele, m4x3f transform,
  * Apply an inverse matrix to all bones which maps vertices from bind space into
  * bone relative positions
  */
-static void skeleton_apply_inverses( struct skeleton *skele, m4x3f *final_mtx ){
-   for( u32 i=0; i<skele->bone_count; i++ ){
+static void skeleton_apply_inverses( struct skeleton *skele, m4x3f *final_mtx )
+{
+   for( u32 i=0; i<skele->bone_count; i++ )
+   {
       struct skeleton_bone *sb = &skele->bones[i];
       m4x3f inverse;
       m3x3_identity( inverse );
       v3_negate( sb->co, inverse[3] );
-
       m4x3_mul( final_mtx[i], inverse, final_mtx[i] );
    }
 }
@@ -337,7 +322,6 @@ static void skeleton_apply_ik_pass( struct skeleton *skele, m4x3f *final_mtx )
    for( u32 i=0; i<skele->ik_count; i++ )
    {
       struct skeleton_ik *ik = &skele->ik[i];
-      
       v3f v0, /* base -> target */
           v1, /* base -> pole */
           vaxis;
@@ -366,12 +350,11 @@ static void skeleton_apply_ik_pass( struct skeleton *skele, m4x3f *final_mtx )
       v2f delta;
       v2_sub( end, base, delta );
 
-      float 
-         l1 = v3_length( skele->bones[ik->lower].end ),
-         l2 = v3_length( skele->bones[ik->upper].end ),
-         d = vg_clampf( v2_length(delta), fabsf(l1 - l2), l1+l2-0.00001f ),
-         c = acosf( (l1*l1 + d*d - l2*l2) / (2.0f*l1*d) ),
-         rot = atan2f( delta[1], delta[0] ) + c - VG_PIf/2.0f;
+      f32 l1 = v3_length( skele->bones[ik->lower].end ),
+          l2 = v3_length( skele->bones[ik->upper].end ),
+          d = vg_clampf( v2_length(delta), fabsf(l1 - l2), l1+l2-0.00001f ),
+          c = acosf( (l1*l1 + d*d - l2*l2) / (2.0f*l1*d) ),
+          rot = atan2f( delta[1], delta[0] ) + c - VG_PIf/2.0f;
 
       knee[0] = sinf(-rot) * l1;
       knee[1] = cosf(-rot) * l1;
@@ -412,8 +395,7 @@ static void skeleton_apply_ik_pass( struct skeleton *skele, m4x3f *final_mtx )
  * Applies the typical operations that you want for an IK rig: 
  *    Pose, IK, Pose(deferred), Inverses, Transform
  */
-static void skeleton_apply_standard( struct skeleton *skele, ms_keyframe *pose,
-                                     m4x3f transform, m4x3f *final_mtx )
+static void skeleton_apply_standard( struct skeleton *skele, ms_keyframe *pose, m4x3f transform, m4x3f *final_mtx )
 {
    skeleton_apply_pose( skele, pose, k_anim_apply_defer_ik, final_mtx );
    skeleton_apply_ik_pass( skele, final_mtx );
@@ -422,10 +404,7 @@ static void skeleton_apply_standard( struct skeleton *skele, ms_keyframe *pose,
    skeleton_apply_transform( skele, transform, final_mtx );
 }
 
-static void skeleton_alloc_from( struct skeleton *skele,
-                                    void *lin_alloc,
-                                    mdl_context *mdl,
-                                    mdl_armature *armature )
+static void skeleton_alloc_from( struct skeleton *skele, void *lin_alloc, mdl_context *mdl, mdl_armature *armature )
 {
    skele->bone_count     = armature->bone_count+1;
    skele->ik_count       = 0;
@@ -434,10 +413,8 @@ static void skeleton_alloc_from( struct skeleton *skele,
    for( u32 i=0; i<armature->bone_count; i++ )
    {
       mdl_bone *bone = &mdl->bones[ armature->bone_start+i ];
-
       if( bone->flags & k_bone_flag_ik )
          skele->ik_count ++;
-
       if( bone->collider )
          skele->collider_count ++;
    }
@@ -452,13 +429,13 @@ static void skeleton_alloc_from( struct skeleton *skele,
    memset( skele->ik, 0, ik_size );
 }
 
-static void skeleton_fatal_err(void){
+static void skeleton_fatal_err(void)
+{
    vg_fatal_error( "Skeleton setup failed" );
 }
 
 /* Setup a skeleton from model. mdl's metadata should stick around */
-void skeleton_setup( struct skeleton *skele, mdl_context *mdl, u32 index,
-                     void *lin_alloc )
+void skeleton_setup( struct skeleton *skele, mdl_context *mdl, u32 index, void *lin_alloc )
 {
    u32 ik_count = 0, collider_count = 0;
    skele->bone_count = 0;
@@ -506,12 +483,13 @@ void skeleton_setup( struct skeleton *skele, mdl_context *mdl, u32 index,
 
       box_copy( bone->hitbox, sb->hitbox );
 
-      if( bone->collider ){
-         if( collider_count == skele->collider_count ){
+      if( bone->collider )
+      {
+         if( collider_count == skele->collider_count )
+         {
             vg_error( "Too many collider bones\n" );
             skeleton_fatal_err();
          }
-
          collider_count ++;
       }
    }
@@ -528,10 +506,11 @@ void skeleton_setup( struct skeleton *skele, mdl_context *mdl, u32 index,
    vg_success( "                     %u colliders\n", skele->collider_count );
 }
 
-static void skeleton_debug( struct skeleton *skele, m4x3f *final_mtx ){
-   for( u32 i=1; i<skele->bone_count; i ++ ){
+static void skeleton_debug( struct skeleton *skele, m4x3f *final_mtx )
+{
+   for( u32 i=1; i<skele->bone_count; i ++ )
+   {
       struct skeleton_bone *sb = &skele->bones[i];
-
       v3f p0, p1;
       v3_copy( sb->co, p0 );
       v3_add( p0, sb->end, p1 );
@@ -539,13 +518,12 @@ static void skeleton_debug( struct skeleton *skele, m4x3f *final_mtx ){
       m4x3_mulv( final_mtx[i], p0, p0 );
       m4x3_mulv( final_mtx[i], p1, p1 );
 
-      if( sb->flags & k_bone_flag_deform ){
-         if( sb->flags & k_bone_flag_ik ){
+      if( sb->flags & k_bone_flag_deform )
+      {
+         if( sb->flags & k_bone_flag_ik )
             vg_line( p0, p1, 0xff0000ff );
-         }
-         else{
+         else
             vg_line( p0, p1, 0xffcccccc );
-         }
       }
       else
          vg_line( p0, p1, 0xff00ffff );
index 066309d44254f4173fcb71a019e0f740eaa1cdf6..d1d9017b9eda4654f8a270ad4d35910545f756d9 100644 (file)
@@ -179,6 +179,7 @@ struct world_instance
                  ent_list,
                  ent_npc,
                  file_entity_ref,
+                 ent_event,
                  ent_script;
    
    GLuint *nonlocal_gates_cubemaps;
index 33651d272a576bfbf7fcb8aa20d447cd57552e30..927e29cf277fae5788832612670257e545990b64 100644 (file)
@@ -129,8 +129,7 @@ void world_gen_entities_init( world_instance *world )
          }
          else
          {
-            clip->_.clip.path = af_str( &world->meta.af, 
-                                         clip->_.file.pstr_path );
+            clip->_.clip.path = af_str( &world->meta.af, clip->_.file.pstr_path );
             clip->_.clip.flags = audio->flags;
             clip->_.clip.any_data = NULL;
             clip->_.clip.size = 0;
@@ -255,77 +254,15 @@ void world_default_spawn_pos( world_instance *world, v3f pos )
    }
 }
 
-entity_call_result ent_volume_call( world_instance *world, ent_call *call )
+static void ent_audio_trigger( ent_audio *audio, v3f sound_co )
 {
-   u32 index = mdl_entity_id_id( call->id );
-   ent_volume *volume = af_arritm( &world->ent_volume, index );
-
-   if( !volume->target ) 
-      return k_entity_call_result_OK;
-
-   if( call->function == k_ent_function_trigger )
-   {
-      call->id = volume->target;
-
-      if( volume->flags & k_ent_volume_flag_particles )
-      {
-         float *co = alloca( sizeof(float)*3 );
-         co[0] = vg_randf64(&vg.rand)*2.0f-1.0f;
-         co[1] = vg_randf64(&vg.rand)*2.0f-1.0f;
-         co[2] = vg_randf64(&vg.rand)*2.0f-1.0f;
-         m4x3_mulv( volume->to_world, co, co );
-
-         call->function = k_ent_function_particle_spawn;
-         call->data = co;
-         entity_call( world, call );
-      }
-      else
-      {
-         call->function = volume->trigger.event;
-         entity_call( world, call );
-      }
-
-      return k_entity_call_result_OK;
-   }
-   else if( call->function == k_ent_function_trigger_leave )
-   {
-      call->id = volume->target;
-
-      if( volume->flags & k_ent_volume_flag_particles )
-         vg_warn( "Invalid condition; calling leave on particle volume.\n" );
-      else
-      {
-         call->function = volume->trigger.event_leave;
-         entity_call( world, call );
-      }
-
-      return k_entity_call_result_OK;
-   }
-
-   return k_entity_call_result_unhandled;
-}
-
-entity_call_result ent_audio_call( world_instance *world, ent_call *call )
-{
-   u32 index = mdl_entity_id_id( call->id );
-   ent_audio *audio = af_arritm( &world->ent_audio, index );
-
-   v3f sound_co;
-
-   if( call->function == k_ent_function_particle_spawn )
-      v3_copy( call->data, sound_co );
-   else if( call->function == k_ent_function_trigger )
-      v3_copy( audio->transform.co, sound_co );
-   else
-      return k_entity_call_result_unhandled;
-
-   float chance = vg_randf64(&vg.rand)*100.0f,
-         bar = 0.0f;
+   world_instance *world = &_world.main;
+   f32 chance = vg_randf64(&vg.rand)*100.0f,
+       bar = 0.0f;
 
    for( u32 i=0; i<audio->clip_count; i++ )
    {
-      ent_audio_clip *clip = af_arritm( &world->ent_audio_clip, 
-                                          audio->clip_start+i );
+      ent_audio_clip *clip = af_arritm( &world->ent_audio_clip, audio->clip_start+i );
 
       float mod = world->probabilities[ audio->probability_curve ],
             p   = clip->probability * mod;
@@ -398,26 +335,58 @@ entity_call_result ent_audio_call( world_instance *world, ent_call *call )
          }
 
          vg_audio_unlock();
-         return k_entity_call_result_OK;
       }
    }
-   return k_entity_call_result_OK;
 }
 
+entity_event_result ent_audio_event( ent_event *event )
+{
+   world_instance *world = &_world.main;
+   ent_audio *audio = af_arritm( &world->ent_audio, mdl_entity_id_id( event->recieve_entity_id ) );
+
+   v3f sound_co;
+   v3_copy( audio->transform.co, sound_co );
+
+   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "spawn_particle" ) )
+   {
+      // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
+      if( mdl_entity_id_type( event->source_entity_id ) == k_ent_volume )
+      {
+         ent_volume *volume = af_arritm( &world->ent_volume, mdl_entity_id_id( event->source_entity_id ) );
+         if( volume->flags & k_ent_volume_flag_particles )
+            v3_copy( volume->particle_co, sound_co );
+         else
+         {
+            vg_error( "Audio particle event; caller not an particle volume (%x).\n", event->source_entity_id );
+            return k_entity_event_result_invalid;
+         }
+      }
+      else
+      {
+         vg_error( "Audio particle event; caller not an ent_volume (%x).\n", event->source_entity_id );
+         return k_entity_event_result_invalid;
+      }
+   }
+   else if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "play" ) ){}
+   else return k_entity_event_result_unhandled;
+
+   ent_audio_trigger( audio, sound_co );
+   return k_entity_event_result_OK;
+}
 
-entity_call_result ent_ccmd_call( world_instance *world, ent_call *call )
+entity_event_result ent_ccmd_event( ent_event *event )
 {
-   if( call->function == k_ent_function_trigger )
+   world_instance *world = &_world.main;
+   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "exec" ) )
    {
-      u32 index = mdl_entity_id_id( call->id );
-      ent_ccmd *ccmd = af_arritm( &world->ent_ccmd, index );
+      ent_ccmd *ccmd = af_arritm( &world->ent_ccmd, mdl_entity_id_id( event->recieve_entity_id ));
       const char *cmd_text = af_str( &world->meta.af, ccmd->pstr_command );
       vg_info( "ccmd: %s\n", cmd_text );
       vg_execute_console_input( cmd_text, 0 );
-      return k_entity_call_result_OK;
+      return k_entity_event_result_OK;
    }
    else
-      return k_entity_call_result_unhandled;
+      return k_entity_event_result_unhandled;
 }
 
 /*
@@ -485,7 +454,7 @@ void entity_bh_expand_bound( void *user, boxf bound, u32 item_index )
       vg_fatal_error( "Programming error\n" );
 }
 
-float entity_bh_centroid( void *user, u32 item_index, int axis )
+f32 entity_bh_centroid( void *user, u32 item_index, int axis )
 {
    world_instance *world = user;
 
@@ -632,13 +601,7 @@ void world_entity_start( world_instance *world, vg_msg *sav )
    {
       ent_audio *audio = af_arritm(&world->ent_audio,i);
       if( audio->flags & AUDIO_FLAG_AUTO_START )
-      {
-         ent_call call;
-         call.data = NULL;
-         call.function = k_ent_function_trigger;
-         call.id = mdl_entity_id( k_ent_audio, i );
-         entity_call( world, &call );
-      }
+         ent_audio_trigger( audio, audio->transform.co );
    }
 
    /* read savedata 
@@ -648,12 +611,8 @@ void world_entity_start( world_instance *world, vg_msg *sav )
    {
       ent_challenge *challenge = af_arritm( &world->ent_challenge, i );
       const char *alias = af_str( &world->meta.af, challenge->pstr_alias );
-
-      u32 result;
-      vg_msg_getkvintg( sav, alias, k_vg_msg_u32, &result, NULL );
-
-      if( result )
-         _ent_challenge_complete( challenge );
+      vg_msg_getkvintg( sav, alias, k_vg_msg_u32, &challenge->status, NULL );
+      _ent_challenge_clear( challenge );
    }
 
    vg_msg routes_block = *sav;
@@ -674,38 +633,16 @@ void world_entity_start( world_instance *world, vg_msg *sav )
             f32 sections[ route->checkpoints_count ];
             vg_msg_cmd cmd;
             if( vg_msg_getkvcmd( &route_info, "sections", &cmd ) )
-            {
                vg_msg_cast( cmd.value, cmd.code, sections, k_vg_msg_f32 | vg_msg_count_bits(route->checkpoints_count) );
-            }
             else
-            {
                for( u32 j=0; j<route->checkpoints_count; j ++ )
                   sections[j] = 0.0f;
-            }
 
             for( u32 j=0; j<route->checkpoints_count; j ++ )
             {
                ent_checkpoint *cp = af_arritm( &world->ent_checkpoint, route->checkpoints_start + j );
                cp->best_time = sections[j];
             }
-
-            /* LEGACY: check if steam achievements can give us a medal */
-            if( steam_ready && steam_stats_ready )
-            {
-               for( u32 j=0; j<VG_ARRAY_LEN(track_infos); j ++ )
-               {
-                  struct track_info *inf = &track_infos[j];
-                  if( !strcmp( inf->name, af_str(&world->meta.af,route->pstr_name)))
-                  {
-                     steamapi_bool set = 0;
-                     if( SteamAPI_ISteamUserStats_GetAchievement( hSteamUserStats, inf->achievement_id, &set ) )
-                     {
-                        if( set )
-                           route->flags |= k_ent_route_flag_achieve_silver;
-                     }
-                  }
-               }
-            }
          }
       }
    }
@@ -749,3 +686,91 @@ void world_entity_serialize( world_instance *world, vg_msg *sav )
       vg_msg_end_frame( sav );
    }
 }
+
+void _world_raise_event( u32 caller, const char *event_alias )
+{
+   world_instance *world = &_world.main;
+   u32 event_alias_hash = vg_strdjb2( event_alias );
+
+   if( mdl_entity_id_type( caller ) != k_ent_volume )
+      vg_low( "%x raises [src_event '%s']\n", caller, event_alias );
+
+   for( u32 i=0; i<af_arrcount( &world->ent_event ); i ++ )
+   {
+      ent_event *event = af_arritm( &world->ent_event, i );
+      if( event->source_entity_id != caller )
+         continue;
+
+      if( af_str_eq( &world->meta.af, event->pstr_source_event, event_alias, event_alias_hash ) )
+      {
+         u32 type = mdl_entity_id_type( event->recieve_entity_id ),
+             index = mdl_entity_id_id( event->recieve_entity_id );
+
+         entity_event_result (*table[])( ent_event *event ) = 
+         {
+            [k_ent_audio]     = ent_audio_event,
+            [k_ent_skateshop] = ent_skateshop_event,
+            [k_ent_objective] = ent_objective_event,
+            [k_ent_ccmd]      = ent_ccmd_event,
+            [k_ent_gate]      = ent_gate_event,
+            [k_ent_challenge] = ent_challenge_event,
+            [k_ent_route]     = ent_route_event,
+            [k_ent_region]    = ent_region_event,
+            [k_ent_glider]    = ent_glider_event,
+            [k_ent_water]     = ent_water_event,
+            [k_ent_npc]       = ent_npc_event,
+            [k_ent_script]    = _ent_script_world_event,
+         };
+
+         if( type >= VG_ARRAY_LEN(table) )
+         {
+            vg_error( "call to entity type: %u is out of range\n", type );
+            return;
+         }
+
+         if( !table[type] )
+         {
+            vg_error( "Entity type %u does not have a call handler, but was called anyway\n", type );
+            return;
+         }
+
+         if( event->flags & k_ent_event_data_const_string )
+         {
+            vg_info( "[event '%s'] %x -> %x ('%s') with '%s'\n", 
+                     af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
+                     event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ), 
+                     af_str( &world->meta.af, event->data.const_pstr ) );
+         }
+         else if( event->flags & k_ent_event_data_const_i32 )
+         {
+            vg_info( "[event '%s'] %x -> %x ('%s') with %d\n", 
+                     af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
+                     event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ), 
+                     event->data.const_i32 );
+         }
+         else if( event->flags & k_ent_event_data_const_f32 )
+         {
+            vg_info( "[event '%s'] %x -> %x ('%s') with %ff\n", 
+                     af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
+                     event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ), 
+                     event->data.const_f32 );
+         }
+         else if( event->flags & k_ent_event_data_const_f32 )
+         {
+            vg_info( "[event '%s'] %x -> %x ('%s') void\n", 
+                     af_str( &world->meta.af, event->pstr_source_event ), event->source_entity_id,
+                     event->recieve_entity_id, af_str( &world->meta.af, event->pstr_recieve_event ));
+         }
+
+         enum entity_event_result res = table[type]( event );
+
+         if( res == k_entity_event_result_unhandled )
+         {
+            vg_warn( "Call to entity %x#%x was unhandled (no event '%s').\n", type, index, 
+                     af_str( &world->meta.af, event->pstr_recieve_event ) );
+         }
+         else if( res == k_entity_event_result_invalid )
+            vg_warn( "Call to entity %x#%x invalid.\n", type, index );
+      }
+   }
+}
index edc85e1e405e6994eb2ad43101def461771cb419..7e392fe140cb6c063f8a15124d5d0374d7b6ef31 100644 (file)
@@ -11,9 +11,9 @@ void world_default_spawn_pos( world_instance *world, v3f pos );
 void world_entity_start( world_instance *world, vg_msg *sav );
 void world_entity_serialize( world_instance *world, vg_msg *sav );
 
-entity_call_result ent_volume_call( world_instance *world, ent_call *call );
-entity_call_result ent_audio_call( world_instance *world, ent_call *call );
-entity_call_result ent_ccmd_call( world_instance *world, ent_call *call );
+//entity_call_result ent_volume_call( world_instance *world, ent_call *call );
+//entity_call_result ent_audio_call( world_instance *world, ent_call *call );
+//entity_call_result ent_ccmd_call( world_instance *world, ent_call *call );
 
 void entity_bh_expand_bound( void *user, boxf bound, u32 item_index );
 float entity_bh_centroid( void *user, u32 item_index, int axis );
@@ -24,3 +24,4 @@ void entity_bh_closest( void *user, u32 item_index, v3f point, v3f closest );
 void update_ach_models(void);
 
 extern bh_system bh_system_entity_list;
+void _world_raise_event( u32 caller, const char *event_alias );
index 086aef453b72b2d101c85d229a606ff9236b9899..c81a8a46a1f15a921be956bb08fc4bfdb47344f6 100644 (file)
@@ -294,20 +294,23 @@ u32 world_intersect_gates( world_instance *world, v3f pos, v3f last )
    return 0;
 }
 
-entity_call_result ent_gate_call( world_instance *world, ent_call *call )
+entity_event_result ent_gate_event( ent_event *event )
 {
-   u32 index = mdl_entity_id_id( call->id );
-   ent_gate *gate = af_arritm( &world->ent_gate, index );
-
-   if( call->function == 0 ) /* unlock() */
-   { 
-      gate->flags &= ~k_ent_gate_locked;
-      return k_entity_call_result_OK;
-   }
-   else 
+   world_instance *world = &_world.main;
+   ent_gate *gate = af_arritm( &world->ent_gate, mdl_entity_id_id( event->recieve_entity_id ) );
+   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "lock" ) )
    {
-      return k_entity_call_result_unhandled;
+      // TODO: Make this dynamiclly fetched from a handler for the entity itself. (or not, fuck you)
+      if( event->flags == k_ent_event_data_const_i32 )
+      {
+         if( event->data.const_i32 ) gate->flags &= ~((u32)k_ent_gate_locked);
+         else                        gate->flags |=   (u32)k_ent_gate_locked;
+         return k_entity_event_result_OK;
+      }
+      else
+         return k_entity_event_result_invalid;
    }
+   else return k_entity_event_result_unhandled;
 }
 
 void nonlocal_gate_cubemap_path( addon_id world_addon_id, const char *gate_key, char path[256] )
index 135d8568c77643cd23738a97b695bc2ff825426f..a11fb00506f0a9b99b402b981acf6a4b4497d5fe 100644 (file)
@@ -27,7 +27,7 @@ int render_gate( world_instance *world, world_instance *world_inside,
 int gate_intersect( ent_gate *gate, v3f pos, v3f last );
 u32 world_intersect_gates( world_instance *world, v3f pos, v3f last );
 
-entity_call_result ent_gate_call( world_instance *world, ent_call *call );
+entity_event_result ent_gate_event( ent_event *event );
 void ent_gate_get_mdl_mtx( ent_gate *gate, m4x3f mmdl );
 
 void world_link_gates( world_instance *world );
index b25e859151931046eab2b125319aecb1c0538f0b..9eb7434b0f8cc2ace5b07c2aede3b35274049d0f 100644 (file)
@@ -107,15 +107,14 @@ static void world_instance_load_mdl( world_instance *world, const char *path, vo
       AF_LOAD_ARRAY_STRUCT( af, &world->ent_ccmd,      ent_ccmd,       heap );
       AF_LOAD_ARRAY_STRUCT( af, &world->ent_objective, ent_objective,  heap );
       AF_LOAD_ARRAY_STRUCT( af, &world->ent_challenge, ent_challenge,  heap );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_relay,     ent_relay,      heap );
       AF_LOAD_ARRAY_STRUCT( af, &world->ent_cubemap,   ent_cubemap,    heap );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_miniworld, ent_miniworld,  heap );
       AF_LOAD_ARRAY_STRUCT( af, &world->ent_prop,      ent_prop,       heap );
       AF_LOAD_ARRAY_STRUCT( af, &world->ent_glider,    ent_glider,     heap );
       AF_LOAD_ARRAY_STRUCT( af, &world->ent_list,      ent_list,       heap );
       AF_LOAD_ARRAY_STRUCT( af, &world->file_entity_ref, file_entity_ref, heap );
       AF_LOAD_ARRAY_STRUCT( af, &world->ent_script, ent_script, heap );
-      AF_LOAD_ARRAY_STRUCT( af, &world->ent_npc, ent_npc, heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_event,     ent_event, heap );
+      AF_LOAD_ARRAY_STRUCT( af, &world->ent_npc,       ent_npc, heap );
    }
 
    array_file_ptr infos;
@@ -530,7 +529,7 @@ void _world_loader_set_addon( addon_id addon_id )
    addon_reg *reg = addon_details(addon_id);
    if( reg->flags & ADDON_REG_MTZERO )
    {
-      u64 status = _skaterift_script_nugget_status( "ch2s5_view" );
+      u64 status = _skaterift_atom_status( "ch2s5_view" );
       
       /* we've seen the cutscene already (1), or about to play it on world load (3).
        * both of those statuses mean we load 'main'. */
index c60ecf17ba722748265db358a71b5d6f4225c3c2..5bd61c420c2430ef37407a01a86a9b35ce9d8a35 100644 (file)
@@ -500,11 +500,16 @@ static void world_render_challenges( world_instance *world, struct world_pass *p
    u32 objective_count = 0,
        challenge_count = 0;
 
+   bool any_order = 0;
+
    if( (_world.event == k_world_event_challenge) && (_world.challenge_state != k_challenge_state_none) )
    {
       u32 challenge_index = mdl_entity_id_id( _world.active_challenge_id );
       ent_challenge *challenge = af_arritm( &world->ent_challenge, challenge_index );
 
+      if( challenge->flags & k_ent_challenge_any_order )
+         any_order = 1;
+
       shader_scene_fxglow_uUvOffset( (v2f){ 8.0f/256.0f, 0.0f } );
       challenge_list[ challenge_count ++ ] = challenge_index;
 
@@ -564,7 +569,7 @@ static void world_render_challenges( world_instance *world, struct world_pass *p
          vg_slewf(&objective->transform.s[0], target, vg.time_frame_delta*4.0f);
          scale = vg_smoothstepf( objective->transform.s[0] );
 
-         if( (objective == _world.challenge_target) || passed )
+         if( (objective == _world.challenge_target) || passed || any_order )
             shader_scene_fxglow_uUvOffset( (v2f){ 16.0f/256.0f, 0.0f } );
          else
             shader_scene_fxglow_uUvOffset( (v2f){ 8.0f/256.0f, 0.0f } );
index 0abcfef83970f3d8fd3f4e5f26634bfba040376d..2d4ccc4673f95980fa6345fd469e65f904134930 100644 (file)
@@ -26,7 +26,8 @@
 
 void world_routes_clear( world_instance *world )
 {
-   for( u32 i=0; i<af_arrcount( &world->ent_route ); i++ ){
+   for( u32 i=0; i<af_arrcount( &world->ent_route ); i++ )
+   {
       ent_route *route = af_arritm( &world->ent_route, i );
       route->active_checkpoint = 0xffff;
    }
@@ -34,7 +35,6 @@ void world_routes_clear( world_instance *world )
    for( u32 i=0; i<af_arrcount( &world->ent_gate ); i++ )
    {
       ent_gate *rg = af_arritm( &world->ent_gate, i );
-
       if( !(rg->flags & k_ent_gate_nonlocal) )
       {
          rg->timing_version = 0;
@@ -122,6 +122,7 @@ static void world_routes_time_lap( u32 route_index )
       if( clean ) route->flags |= k_ent_route_flag_achieve_gold;
       ent_region_re_eval( world );
 
+#if 0
       struct ent_script_event event;
       struct script_event_completion_changed inf = {
          .entity_id = mdl_entity_id( k_ent_route, route_index ),
@@ -130,6 +131,7 @@ static void world_routes_time_lap( u32 route_index )
       event.type = k_escript_event_completion_changed;
       event.info = &inf;
       ent_script_propogate_event( world, &event );
+#endif
 
       /* for steam achievements. */
       if( route->anon.official_track_id != 0xffffffff )
index 6d7d859c8d59b33d1391498add5caab330eb4a35..c6b3dd2fc6b2b269dec94b98a04f89d661a231b0 100644 (file)
@@ -8,8 +8,9 @@ void world_volumes_update( world_instance *world, v3f pos )
    u32 j=0;
    for( u32 i=0; i<_world.active_trigger_volume_count; i++ )
    {
-      i32 idx = _world.active_trigger_volumes[i];
-      ent_volume *volume = af_arritm( &world->ent_volume, idx );
+      i32 index = _world.active_trigger_volumes[i];
+      u32 id = mdl_entity_id( k_ent_volume, index );
+      ent_volume *volume = af_arritm( &world->ent_volume, index );
 
       bool in_volume = 1;
 
@@ -23,9 +24,10 @@ void world_volumes_update( world_instance *world, v3f pos )
 
       if( in_volume )
       {
-         _world.active_trigger_volumes[ j ++ ] = idx;
+         _world.active_trigger_volumes[ j ++ ] = index;
          boxf cube = {{-1.0f,-1.0f,-1.0f},{1.0f,1.0f,1.0f}};
          vg_line_boxf_transformed( volume->to_world, cube, 0xff00ccff );
+         _world_raise_event( id, "stay" );
       }
       else
       {
@@ -39,21 +41,7 @@ void world_volumes_update( world_instance *world, v3f pos )
                }
             }
          }
-         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 );
-            }
-         }
+         _world_raise_event( id, "leave" );
       }
    }
    _world.active_trigger_volume_count = j;
@@ -96,17 +84,18 @@ void world_volumes_update( world_instance *world, v3f pos )
 
       if( volume->flags & k_ent_volume_flag_particles )
       {
-         vg_line_boxf_transformed( volume->to_world, cube, 0xff00c0ff );
-
          for( int j=0; j<random_ticks; j++ )
          {
-            ent_call basecall;
-            basecall.id = id;
-            basecall.data = NULL;
-            basecall.function = 0;
-
-            entity_call( world, &basecall );
+            v3f co;
+            co[0] = vg_randf64(&vg.rand)*2.0f-1.0f;
+            co[1] = vg_randf64(&vg.rand)*2.0f-1.0f;
+            co[2] = vg_randf64(&vg.rand)*2.0f-1.0f;
+            m4x3_mulv( volume->to_world, co, volume->particle_co );
+            _world_raise_event( id, "particle" );
          }
+
+         vg_line_boxf_transformed( volume->to_world, cube, 0xff00c0ff );
+         vg_line_cross( volume->particle_co, 0xffa0a0a0, 1.0f );
       }
       else
       {
@@ -132,24 +121,20 @@ void world_volumes_update( world_instance *world, v3f pos )
             {
                if( localplayer.subsystem == k_player_subsystem_walk )
                {
-                  if( world_set_event( k_world_event_interact ) )
+                  if( _world.event == k_world_event_none )
                   {
-                     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;
+                     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 = id;
+                     }
                   }
                }
             }
-            else
-            {
-               ent_call basecall;
-               basecall.function = 0;
-               basecall.id = id;
-               basecall.data = NULL;
-               entity_call( world, &basecall );
-            }
+            _world_raise_event( id, "enter" );
             _world.active_trigger_volumes[ _world.active_trigger_volume_count ++ ] = index;
          }
          else
@@ -160,36 +145,30 @@ next_volume:;
 
    if( _world.event == k_world_event_interact )
    {
-      ent_volume *volume = _world_volumes.active_volume_interact;
+      u32 id = _world_volumes.active_volume_interact;
+      ent_volume *volume = af_arritm( &world->ent_volume, mdl_entity_id_id( id ) );
       if( volume->flags & k_ent_volume_flag_disabled )
       {
          /* might get turned off by another system eg scripts */
          if( world_clear_event( k_world_event_interact ) )
          {
-            _world_volumes.active_volume_interact = NULL;
+            _world_volumes.active_volume_interact = 0;
             gui_helper_reset( k_gui_helper_mode_clear );
          }
       }
       else if( button_down( k_srbind_maccept ) )
       {
-         if( volume->target )
+         srinput.state = k_input_state_resume;
+         if( !(volume->flags & k_ent_volume_flag_repeatable) )
          {
-            srinput.state = k_input_state_resume;
-            if( !(volume->flags & k_ent_volume_flag_repeatable) )
+            if( world_clear_event( k_world_event_interact ) )
             {
-               if( world_clear_event( k_world_event_interact ) )
-               {
-                  _world_volumes.active_volume_interact = NULL;
-                  gui_helper_reset( k_gui_helper_mode_clear );
-               }
+               _world_volumes.active_volume_interact = 0;
+               gui_helper_reset( k_gui_helper_mode_clear );
             }
-
-            ent_call call;
-            call.data = NULL;
-            call.function = volume->interact.activate_event;
-            call.id = volume->target;
-            entity_call( &_world.main, &call );
          }
+
+         _world_raise_event( id, "use" );
       }
    }
 }
index f9a7481ff659cf3423d9524de020488470cfb6ae..06ccf5f31b79bf58a79159fc8e74e01f6af0358c 100644 (file)
@@ -4,7 +4,7 @@
 
 struct _world_volumes
 {
-   ent_volume *active_volume_interact;
+   u32 active_volume_interact;
 }
 extern _world_volumes;
 
index f9ced3f3dc6650018de442c33f6abc5f3a2579c3..e9e74ef55da2f7c964f6095ce0180398948f5d9c 100644 (file)
@@ -265,13 +265,13 @@ bool world_water_player_safe( world_instance *world, f32 allowance )
    return 1;
 }
 
-entity_call_result ent_water_call( world_instance *world, ent_call *call )
+entity_event_result ent_water_event( ent_event *event )
 {
-   if( call->function == 0 )
+   world_instance *world = &_world.main;
+   if( AF_STR_EQ( &world->meta.af, event->pstr_recieve_event, "drown" ) )
    {
       world_water_drown();
-      return k_entity_call_result_OK;
+      return k_entity_event_result_OK;
    }
-
-   return k_entity_call_result_unhandled;
+   else return k_entity_event_result_unhandled;
 }
index 7ff9af57ddf6ec34eccf6773a382debc99a46057..b2d753da21f35261b811cc66d09db769ddd9be47 100644 (file)
@@ -14,5 +14,5 @@ void world_water_init(void);
 void water_set_surface( world_instance *world, f32 height );
 void render_water_texture( world_instance *world, vg_camera *cam );
 void render_water_surface( world_instance *world, vg_camera *cam );
-entity_call_result ent_water_call( world_instance *world, ent_call *call );
+entity_event_result ent_water_event( ent_event *event );
 bool world_water_player_safe( world_instance *world, f32 allowance );