|
2 registered members (JeyKey II, 1 invisible),
3,478
guests, and 1
spider. |
|
Key:
Admin,
Global Mod,
Mod
|
|
|
Re: Parent/child object
[Re: Frederick_Lim]
#489632
09/11/26 06:21
09/11/26 06:21
|
Joined: May 2009
Posts: 5,378 Caucasus
3run
Senior Expert
|
Senior Expert
Joined: May 2009
Posts: 5,378
Caucasus
|
Nope, you'll have to move/rotate it by yourself. In action function of ENTITY a, you could create ENTITY b as it's parent. Then in while loop at the very end (after moving ENTITY a) you could check, if ENTITY b exists, and if it does, then move/rotate it with ENTITY a. action move_test()
{
my.parent = ent_create(CUBE_MDL, my.x, NULL);
while(my)
{
// move my
if(my.parent)
{
vec_set(my.parent.x, my.x);
vec_set(my.parent.pan, my.pan);
}
wait(1);
}
}
|
|
|
Re: Parent/child object
[Re: Frederick_Lim]
#489654
09/22/26 05:52
09/22/26 05:52
|
Joined: Jun 2008
Posts: 60 Caucasus
VoroneTZ
Junior Member
|
Junior Member
Joined: Jun 2008
Posts: 60
Caucasus
|
You can also use bones to attach objects to specific parts of the model. action attach_gun_to_actor
{
var anim_percent = 0;
you = ent_create("gun.mdl", vector(0,0,0), NULL); // create gun entity without animation
while(1)
{
anim_percent += time_step;
ent_animate(me, "walk", anim_percent, ANM_CYCLE);
//attach gun to "RightHand" bone
vec_for_bone(your.x, my, "RightHand"); // move gun entity
ang_for_bone(your.pan, my, "RightHand"); // rotate entity
wait(1);
}
}
|
|
|
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
|