|
|
Re: Parent/child object
[Re: Frederick_Lim]
#489669
09/27/26 14:43
09/27/26 14:43
|
Joined: Jul 2008
Posts: 2,125 Germany
rayp
 
X
|
 
X
Joined: Jul 2008
Posts: 2,125
Germany
|
"Map entities" might work for you. A collection of entites / blocks in a WMB file loaded via ent_create (if you jiust want to "combine" static models but not moving) If not:
#define anm_frame skill80
var level_loading = 0;
action Actor_with_Gun_WED(){
while (my && level_loading) wait (1); // wait for level loading is done!
ENTITY* ent = ent_create("gun.mdl", vector(0,0,0), NULL); // create gun entity without action
//if (!ent){ safe_remove (me; return; }
while(my && !level_loading){
//if (!freeze_mode){
my.anm_frame += time_step;
my.anm_frame %= 100;
ent_animate(me, "walk", my.anm_frame, ANM_CYCLE);
if (ent){ // always check for valid pointers
//attach gun to "RightHand" bone
vec_for_bone(ent.x, my, "RightHand"); // move gun entity
//vec_for_vertex (ent.x, my, "123");
ang_for_bone(ent.pan, my, "RightHand"); // rotate entity
}
//}
wait(1);
}
//wait(1);//super safe XD
if (ent){
safe_remove (ent);
//ent = NULL; // global pointers only
}
safe_remove (me);
}
...
// safe level switch "no matter what"
level_loading = 1;
wait (-1);
level_load ("map2.wmb");
wait (5);
level_loading = 0;
...
"safe" global entity usage
ENTITY* ent_global_example;
action Blupp(){
// wait (1);
// set bbox etc
ent_global_example = me;
while (my && level_loading) wait (1);
while (my && !level_loading){
...
wait (1);
}
safe_remove (me);
ent_global_example = NULL;
}
action Bla(){
while (my && level_loading) wait (1);
//while (!ent_global_example) wait (1); // we check for it in the while anyway...
...
while (my && !level_loading){
if (ent_global_example){
...
}
wait (1);
}
safe_remove (me);
}
I try to use event_frame whenever possible (but with sub ents i would prefer while's too i have to say because with event_frame you might end up with XYZ/Pan,Tilt,Roll that are one frame to old!). Code below not tested but it should work:
#define anm_frame skill80
#define sub_ent_handle skill79
var level_loading = 0;
void event_testactor_wed(){
if (event_type == EVENT_FRAME && my.sub_ent_handle){
ENTITY* ent = ptr_for_handle (my.sub_ent_handle);
if (ent && !level_loading && !freeze_mode){
my.anm_frame += time_step;
my.anm_frame %= 100;
ent_animate (me, "idle", my.anm_frame, ANM_CYCLE);
vec_for_bone (ent.x, my, "RightHand");
ang_for_bone (ent.pan, my, "RightHand");
}
if (level_loading){
my.event = NULL;
if (ent) safe_remove (ent);
//ent = NULL; // global pointers
safe_remove (me);
//return; // if more event code below!
}
}
}
action TestActor_WED(){
while (my && level_loading) wait (1);
ENTITY* ent = ent_create ("gun.mdl", vector (0,0,0), NULL);
if (!ent){
safe_remove (me);
return;
}
else{
my.sub_ent_handle = handle (ent);
my.emask |= ENABLE_FRAME;
my.event = event_testactor_wed;
}
}
Or instead of ptr_for_handle its possible to use a global entity pointer, if the sub ent is only used by one entity. Another way, maybe more clean with more actors
#define anm_frame skill80
#define right_handed skill79
var level_loading = 0;
void attach_gun_to_actors (ENTITY* ent_actor, ent_gun){
if (!ent_actor || !ent_gun) return;
VECTOR tmp_pos;
ANGLE tmp_ang;
if (ent_actor.right_handed){
vec_for_bone (tmp_pos, ent_actor, "RightHand");
ang_for_bone (tmp_ang, ent_actor, "RightHand");
}
else{
vec_for_bone (tmp_pos, ent_actor, "LeftHand");
ang_for_bone (tmp_ang, ent_actor, "LeftHand");
}
vec_set (ent_gun.x, tmp_pos.x);
vec_set (ent_gun.pan, tmp_ang.pan);
}
/* The "skill1-line" is no comment instead WED will show "RightHanded" in object properties instead of "Skill1" (reload wmp or main script to show) ;)
Of course it makes no sense to use two skills for RightHanded...i just wanted to show this nice "hidden" WED feature here
That’s why I always go from high skill #defines down to low ones, so that the first skills can be used in WED. */
//skill1 RightHanded 1
action Actor_WED(){
while (my && level_loading) wait (1);
my.right_handed = my.skill1;
ENTITY* tmp_gun = ent_create ("gun.mdl", vector (0,0,0), NULL);
if (!tmp_gun){ safe_remove (me); return; }
while (my && !level_loading){
my.anm_frame += time_step;
my.anm_frame %= 100;
ent_animate (me, "idle", my.anm_frame, ANM_CYCLE);
attach_gun_to_actors (me, tmp_gun);
wait (1);
}
if (tmp_gun) safe_remove (tmp_gun);
safe_remove (me);
}
...
level_loading = 1;
wait (-1);
level_load ("map2.wmb");
wait (5);
level_loading = 0;
...
While the "level_loading" stuff may be optional at first, it makes things so much safer and easier later on, especially when it comes to interactions between multiple global pointers. Just wanted to say using stuff like "while(1)" with (global-) pointers can become dangerous very quick. I hope those example are "safe enough" for entity pointer usage and level switching. It's a good idea to set in your main function to keep constant! Btw...I prefer a struct with entities, very clean, easy and good for many sub ents.Greets
Acknex umgibt uns...zwischen Dir, mir, dem Stein dort... "Hey Griswold ... where u gonna put a tree that big ?" 1998 i married my loved wife ... Sheeva from Mortal Kombat, not Evil-Lyn as might have been expected rayp.flags |= UNTOUCHABLE;
|
|
|
Moderated by mk_1, Perro, rayp, Realspawn, Rei_Ayanami, rvL_eXile, Spirit, Superku, Tobias, TSG_Torsten, VeT
|