Inside3D!
     

movement on the surface

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming
View previous topic :: View next topic  
Author Message
delta54



Joined: 28 Feb 2010
Posts: 3
Location: Russia

PostPosted: Sun Feb 28, 2010 1:15 pm    Post subject: movement on the surface Reply with quote

Hi not long ago began to study quakec, there were several issues to resolve please help.
engine: Darkplaces


why can not move forward:
http://www.youtube.com/watch?v=KfVBmsRJrK8






Code:

#define MONSTES_ENABLED
#ifdef MONSTES_ENABLED

#define crab_anim_idle         0
#define crab_anim_walk         1
#define crab_anim_spawn        2
#define crab_anim_die          3
#define crab_anim_dead         4

#define CRAB_MIN                '-5 -5 0'
#define CRAB_MAX                '5 5 5'

#define CR_IDLE     10

#define CR_PATH     100
#define CR_HUNT     200

#define CR_ATTACK_FIND  10
#define CR_ATTACK_RUN   20
#define CR_ATTACK_STAND 30

#define CR_PATH2 10000

#define MONSTERFLAG_NORESPAWN_CR 2


void crab_spawn();

float crab_scoretarget(entity trg)                              // Оценка цели
{
    float  tmp;                                    // Определяем 32 разрядную переменную tmp
    vector ang1;                                 // Определяем вектор



    if (trg.takedamage == DAMAGE_AIM)                              // Если не цель, не трогать
    if not (trg.flags & FL_NOTARGET)                              // Если нет флага notarget
    if (trg.deadflag == DEAD_NO)                              // Если мертв, не трогать
//     if (trg.team != self.team)                                 // Если свой, не трогать
    if (trg.classname == "point")
    {
        if((self.origin_z - trg.origin_z) < 128)                        // Определяем расстояние по Z
        {
            ang1 = normalize(self.origin - trg.origin);                        // Определяем расстояние по Z
            tmp = vlen(ang1 - v_forward);            // Возвращает длину вектора (Расстояние - смотреть вперед)
            if(tmp > 1.5)                                 // НЕ ПОНЯТНО !!!
            {
                traceline(self.origin + '0 0 5',trg.origin + '0 0 1',MOVE_NORMAL,self);         // Функция: traceline
                if(trace_ent != trg)               // Получаем глобадбную переменную, если не равна trg возвращаем 0
                    return 0;

                return (cvar("g_monster_crab_targetrange") - vlen(self.origin - trg.origin)) * tmp;       // Цель враг
            }
            else if(self.enemy == trg)
                return (cvar("g_monster_crab_targetrange") - vlen(self.origin - trg.origin)) * tmp;      // Цель враг
        }
    }

    return 0;                                       // Цель не враг
}

void crab_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)  // остатки , если стрелять разлетаются
{
//     dprint("crab_corpse_damage\n");
    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 160, self, attacker);

    self.health -= damage;                                    // Вычитаем урон

    if(self.health < 0)                                       // Если у тела переменная health<0 то переходим дальше
    {
        remove(self);                                       // Удалить тело после выстрела
    }
}

void crab_die(vector dir)                              // die
{
    entity dummy;                                 // Определяем лицо-пустышку

    dummy = spawn();                                 // Создаем точку входа пустышки
    setmodel(dummy,"models/monsters/crab.dpm");                        // Определяем модель пустышки
    setorigin(dummy, self.origin);                           // Указываем позицию по вектору self.origin
    dummy.velocity  = self.velocity;                           // Направление отскакивания тела
    dummy.movetype  = MOVETYPE_BOUNCE;                           // Тип движения (MOVETYPE_BOUNCE = отскакивают от стен)
    dummy.think     = SUB_Remove;                           // ? функция удаления
    dummy.nextthink = time + 3;                              // Вызывать каждые n число секунд
    dummy.health    = 50;                              // жизней у трупа, если ноль то куски
    dummy.takedamage = DAMAGE_YES;                           // Тип Damage (DAMAGE_YES) Гранаты не взрываются при прикосновении
    dummy.event_damage = crab_corpse_damage;                        // В случае повреждения вызываем функцию "crab_corpse_damage" !!!!!!!!!
    dummy.solid      = SOLID_CORPSE;                           // тип бокса тела
    setsize(dummy,self.mins,self.maxs);                           // Размер бокса тела setsize(entity, vector_min, vector_max);

    SUB_SetFade(dummy,time + 50,2);                           // Время жизни тела


    dummy.frame = crab_anim_die;                           // play die animation
   
    if(self.spawnflags & MONSTERFLAG_NORESPAWN_CR)               // Если спаун флаг стоит и MONSTERFLAG_NORESPAWN присутствует
    {
        self.think = SUB_Remove;                  // ? функция удаления или обновления
        self.nextthink = time;                     // обновлять по времени
        return;
    }

    setmodel(self,"");                        // Удаляем все
    self.solid          = SOLID_NOT;
    self.takedamage     = DAMAGE_NO;
    self.event_damage   = SUB_Null;
    self.enemy          = world;
    self.think          = crab_spawn;
    self.nextthink      = time + cvar("g_monster_crab_respawntime");      // Ждем конца времени респавна
    self.pain_finished  = self.nextthink;
}

void crab_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
    self.health -= damage;
    self.velocity = self.velocity + force;
    if(self.health <= 0)
    {
        crab_die(hitloc);
        return;
    }

    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 160, self, attacker);

   if (damage > 50)
      Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker);
   if (damage > 100)
      Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker);
   
}

.vector bvec;
.float bvec_time;

void crab_move()                     // Движение
{
    vector real_angle;                     // Объявляем вектор
    float vz, tdiff, tspeed;                  // Объявляем переменные

    tdiff = time - self.zoomstate;               // Присваеваем значение
    tspeed = tdiff * cvar("g_monster_crab_turnspeed");         // Присваеваем значение g_monster_crab_turnspeed(скорость)
    vz = self.velocity_z;                  //

    if(self.bvec_time < time)                              // вращение
    {
        self.bvec_time = time + 0.2;
        self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64);
    }

    if(self.enemy)                                 // Если виден враг, то двигатьсяк к нему
        self.moveto = self.enemy.origin;                        // Координаты врага self.enemy.origin

    else
        self.moveto = self.origin + v_forward;                        // Двигаться вперед

    self.steerto = normalize(steerlib_attract2(self.moveto,500,500,0.95) + self.bvec);
   
    self.angles_x = safeangle(self.angles_x);
    self.angles_y = safeangle(self.angles_y);
    self.angles_z = safeangle(self.angles_z);
    dprint("x= ", ftos(self.angles_x), "\n");
    dprint("y= ", ftos(self.angles_y), "\n");
    dprint("z= ", ftos(self.angles_z), "\n");
    real_angle = vectoangles(self.steerto) - self.angles;
    dprint("real_angle= ", vtos(real_angle), "\n");
    self.angles_y += bound(-10, real_angle_y, 10);                     // Угол поворота 10

    if(vlen(self.origin - self.moveto) > 15)
    {
        movelib_move_simple(v_forward ,cvar("g_monster_crab_movespeed"),0.6);
        if(time > self.pain_finished)
            if(self.attack_finished_single < time)
                self.frame = crab_anim_walk;                     // Анимация crab_anim_runforward
    }
    else
    {
        movelib_beak_simple(cvar("g_monster_crab_stopspeed"));
        if(time > self.pain_finished)
            if(self.attack_finished_single < time)
                self.frame = crab_anim_idle;                        // Анимация crab_anim_idle
    }

    self.velocity_z = vz;
    self.steerto = self.origin;
}

float crab_verb_idle_roam(float eval)
{
    switch (eval)
    {
    case VCM_EVAL:

        if(self.enemy)
            return VS_CALL_NO;

        return verb.verb_static_value;

    case VCM_DO:

        self.moveto = v_forward * 128;
        self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64);

        return VS_CALL_YES_DOING;
    }

    return VS_CALL_YES_DONE;
}

float crab_verb_idle_stand(float eval)
{
    switch (eval)
    {
    case VCM_EVAL:

        if(self.enemy)
            return VS_CALL_NO;

        return verb.verb_static_value;

    case VCM_DO:

        self.moveto   = self.origin;
        self.frame    = crab_anim_idle;
        self.velocity = '0 0 0';

        return VS_CALL_YES_DOING;
    }

    return VS_CALL_YES_DONE;
}

float crab_verb_idle(float eval)                  // Ожидаем
{
    switch (eval)
    {
    case VCM_EVAL:                        // Случай

        if(self.enemy)                        // Если лицо-ВРАГ возвращаем VS_CALL_NO
            return VS_CALL_NO;

        return verb.verb_static_value;                  // Возвращаем verb.verb_static_value

    case VCM_DO:
        float t;

        t = cvar("g_monster_crab_idle_timer_max") -  cvar("g_monster_crab_idle_timer_min");
        t = cvar("g_monster_crab_idle_timer_min") + (random() * t);

        if(random() < 0.5)
   {
            verbstack_push(self.verbs_idle, crab_verb_idle_roam,  CR_IDLE + 1, t, self);   
   }
        else
   {
            verbstack_push(self.verbs_idle, crab_verb_idle_stand, CR_IDLE + 1, 0.1, self);
   }
        return VS_CALL_YES_DOING;
    }

    return VS_CALL_YES_DONE;
}

float crab_verb_attack_findtarget(float eval)
{
    switch (eval)
    {
    case VCM_EVAL:
        if(self.enemy)
            return VS_CALL_NO;

        return verb.verb_static_value;

    case VCM_DO:

        entity trg, best_trg;
        float trg_score, best_trg_score;

        trg = findradius(self.origin,cvar("g_monster_crab_targetrange"));
        while(trg)
        {
            trg_score = crab_scoretarget(trg);
            if(trg_score > best_trg_score)
            {
                best_trg = trg;
                best_trg_score = trg_score;
            }

            trg = trg.chain;
        }

        if(best_trg)
        {
            self.enemy = best_trg;
            dprint("Crab sees: ",best_trg.netname, " as target.\n");
        }

        return VS_CALL_YES_DOING;
    }

    return VS_CALL_YES_DONE;
}

void crab_runattack_damage()
{
    entity oldself;
    oldself = self;
    self = self.owner;

    if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_crab_attack_run_hitrange"))
        return;

    if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
        return;

    Damage(self.enemy, self, self, cvar("g_monster_crab_attack_run_damage"), DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin)  * cvar("g_monster_crab_attack_run_force"));

    self = oldself;
    self.think = SUB_Remove;
    self.nextthink = time;
}

float crab_verb_attack_run(float eval)
{
    switch (eval)
    {
    case VCM_EVAL:
        if not (self.enemy)
            return VS_CALL_NO;

        if(self.attack_finished_single > time)
            return VS_CALL_NO;

        if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_crab_attack_run_range"))
            return VS_CALL_NO;

        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
            return VS_CALL_NO;

        return verb.verb_static_value;

    case VCM_DO:
        entity pain;
        pain = spawn();
        pain.owner = self;
        pain.think = crab_runattack_damage;
        pain.nextthink = time + cvar("g_monster_crab_attack_run_delay");

        self.attack_finished_single = time + 0.7;
        self.frame = crab_anim_idle;

        return VS_CALL_YES_DOING;
    }

    return VS_CALL_YES_DONE;
}

void crab_standattack_damage()
{
    //entity oldself;
    //oldself = self;
    //self = self.owner;

    setorigin(self,self.owner.origin + v_forward * 32);
    RadiusDamage(self, self.owner, cvar("g_monster_crab_attack_stand_damage"),cvar("g_monster_crab_attack_stand_damage"),16,self, cvar("g_monster_crab_attack_stand_force"),DEATH_TURRET,world);
    //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)


    //self = oldself;
    self.think = SUB_Remove;
    self.nextthink = time;
}

float crab_verb_attack_stand(float eval)
{
    switch (eval)
    {
    case VCM_EVAL:
        if not (self.enemy)
            return VS_CALL_NO;

        if(self.attack_finished_single > time)
            return VS_CALL_NO;

        if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_crab_attack_stand_range"))
            return VS_CALL_NO;

        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8)
            return VS_CALL_NO;

        return verb.verb_static_value;

    case VCM_DO:
        entity pain;
        pain = spawn();
        pain.owner = self;
        pain.think = crab_runattack_damage;
        pain.nextthink = time + cvar("g_monster_crab_attack_stand_delay");

        self.attack_finished_single = time + 0.7;
        self.frame = crab_anim_idle;
        dprint("frame:",ftos(self.frame),"\n");

        return VS_CALL_YES_DOING;
    }

    return VS_CALL_YES_DONE;
}

void crab_think()                  // Размышлегия оО
{   
    self.angles_x *= -1;               // Векторы
    makevectors(self.angles);
    self.angles_x *= -1;

    if (crab_scoretarget(self.enemy) == 0)         // Поиск врага по функции crab_scoretarget()
        self.enemy = world;               // не найден, продолжаем поиск

    verbstack_pop(self.verbs_attack);            // найден

    if not (self.enemy)                  // Если не враг, ожидание
        verbstack_pop(self.verbs_idle);

    crab_move();                  // Движение

    if(self.enemy)                  // Счетчик ?
        self.nextthink = time;
    else
        self.nextthink = time + 0.2;
}

void crab_spawn()                           // Spawn()
{
    setmodel(self,"models/monsters/crab.dpm");                  // Указываем модель

    self.solid          = SOLID_BBOX;                     // Тип бокса
    self.takedamage     = DAMAGE_AIM;                     // Тип Damage
    self.event_damage   = crab_damage;                     // В случае повреждения вызывается функция crab_damage()
    self.enemy          = world;                     // Что-то про врага
    self.frame          = crab_anim_spawn;                  // Проигрываем анимацию crab_anim_spawn
    self.think          = crab_think;                     // вызывается функция crab_think()
    self.nextthink      = time + 2.1;                     // Следующий вызов через time + 2.1
    self.pain_finished  = self.nextthink;                  // time when pain sound is finished
    self.movetype       = MOVETYPE_WALK;                  // Тип передвижения
    self.health         = cvar("g_monster_crab_health");            // Количество жизней
    self.velocity       = '0 0 0';                     // Направление вектора
    self.angles         = self.pos2;                     //
    self.moveto         = self.origin;                     //
    self.flags          = FL_MONSTER;                     // Определяем как монстра

    setorigin(self,self.pos1);                        // Позиция
    setsize(self,CRAB_MIN,CRAB_MAX);                     // Размер бокса
}


void spawnfunc_monster_crab()
{
    if not(cvar("g_monsters"))                        // Если нет переменной то все удаляем лицо
    {
        remove(self);
        return;
    }

    precache_model("models/monsters/crab.dpm");                  // Кешируем модель


    self.verbs_idle   = spawn();                     // прикрепляем ожидание
    self.verbs_attack = spawn();                     //  .... атаку

    self.verbs_idle.owner = self;                     // что то там с владельцем
    self.verbs_attack.owner = self;

    self.think      = crab_spawn;                     // Намеринья ) переходим на функцию crab_spawn()
    self.nextthink  = time + 2;                        // Ждем перед слдуюжим действием

    traceline(self.origin + '0 0 0', self.origin - '0 0 5', MOVE_WORLDONLY, self);   // Функция: traceline

    self.pos1 = trace_endpos;                        // ?
    self.pos2 = self.angles;                        // ?
    self.team = MAX_SHOT_DISTANCE -1;                     // ?

    verbstack_push(self.verbs_idle, crab_verb_idle, CR_IDLE,0 , self);         // Переходим на функцию crab_verb_idle

    verbstack_push(self.verbs_attack, crab_verb_attack_findtarget, CR_ATTACK_FIND,0 , self);
    verbstack_push(self.verbs_attack, crab_verb_attack_run, CR_ATTACK_RUN,0 , self);
    verbstack_push(self.verbs_attack, crab_verb_attack_stand, CR_ATTACK_STAND,0 , self);

}

#endif   // MONSTES_ENABLED





I can not solve the problem:

1. motion parallel to the surface
2. why slips
Back to top
View user's profile Send private message Visit poster's website
Spike



Joined: 05 Nov 2004
Posts: 944
Location: UK

PostPosted: Sun Feb 28, 2010 5:24 pm    Post subject: Reply with quote

MOVETYPE_WALK never becomes a no-op.
What I mean by that, is that gravity is always applied.
And because its on a slope, it'll rebound in a non-vertical direction.
Basically, it slides because its MOVETYPE_WALK.

MOVETYPE_WALK is basically MOVETYPE_TOSS on ice, with the ability to step. It slides. Constantly.

It stops on the slope because its not moving fast enough to overcome gravity.
See what happens if you set .gravity to 0.0001
_________________
What's a signature?
Back to top
View user's profile Send private message Visit poster's website
delta54



Joined: 28 Feb 2010
Posts: 3
Location: Russia

PostPosted: Sun Feb 28, 2010 5:53 pm    Post subject: Reply with quote

Spike wrote:
MOVETYPE_WALK never becomes a no-op.
What I mean by that, is that gravity is always applied.
And because its on a slope, it'll rebound in a non-vertical direction.
Basically, it slides because its MOVETYPE_WALK.

MOVETYPE_WALK is basically MOVETYPE_TOSS on ice, with the ability to step. It slides. Constantly.

It stops on the slope because its not moving fast enough to overcome gravity.
See what happens if you set .gravity to 0.0001

Thanks, added self.gravity = 0.01; helped.
Back to top
View user's profile Send private message Visit poster's website
delta54



Joined: 28 Feb 2010
Posts: 3
Location: Russia

PostPosted: Sun Feb 28, 2010 5:55 pm    Post subject: Reply with quote

how to know the angle of inclination of the surface normal under self.origin ?
Back to top
View user's profile Send private message Visit poster's website
Urre



Joined: 05 Nov 2004
Posts: 1073
Location: Sweden

PostPosted: Sun Feb 28, 2010 6:42 pm    Post subject: Reply with quote

tracebox(self.origin, self.mins, self.maxs, self.origin + '0 0 -1', FALSE, self);
if (trace_fraction < 1 && trace_plane_normal_z > 0.7) // we're on ground, and not on a slope too steep

And to answer the question, trace_plane_normal is set by traceline and tracebox, when it hits something.
_________________
Look out for Twigboy
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2004 phpBB Group