View previous topic :: View next topic |
Author |
Message |
delta54
Joined: 28 Feb 2010 Posts: 3 Location: Russia
|
Posted: Sun Feb 28, 2010 1:15 pm Post subject: movement on the surface |
|
|
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 |
|
 |
Spike
Joined: 05 Nov 2004 Posts: 944 Location: UK
|
Posted: Sun Feb 28, 2010 5:24 pm Post subject: |
|
|
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 |
|
 |
delta54
Joined: 28 Feb 2010 Posts: 3 Location: Russia
|
Posted: Sun Feb 28, 2010 5:53 pm Post subject: |
|
|
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 |
|
 |
delta54
Joined: 28 Feb 2010 Posts: 3 Location: Russia
|
Posted: Sun Feb 28, 2010 5:55 pm Post subject: |
|
|
how to know the angle of inclination of the surface normal under self.origin ? |
|
Back to top |
|
 |
Urre

Joined: 05 Nov 2004 Posts: 1073 Location: Sweden
|
Posted: Sun Feb 28, 2010 6:42 pm Post subject: |
|
|
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 |
|
 |
|
|
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
|