]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/turrets/turret/walker.qc
Hide the MOTD when going spec
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / turrets / turret / walker.qc
1 #ifndef TURRET_WALKER_H
2 #define TURRET_WALKER_H
3
4 //#define WALKER_FANCYPATHING
5
6 #include "walker_weapon.qc"
7
8 CLASS(WalkerTurret, Turret)
9 /* spawnflags */ ATTRIB(WalkerTurret, spawnflags, int, TUR_FLAG_PLAYER | TUR_FLAG_MOVE);
10 /* mins       */ ATTRIB(WalkerTurret, mins, vector, '-70 -70 0');
11 /* maxs       */ ATTRIB(WalkerTurret, maxs, vector, '70 70 95');
12 /* modelname  */ ATTRIB(WalkerTurret, mdl, string, "walker_body.md3");
13 /* model      */ ATTRIB(WalkerTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
14 /* head_model */ ATTRIB(WalkerTurret, head_model, string, strzone(strcat("models/turrets/", "walker_head_minigun.md3")));
15 /* netname    */ ATTRIB(WalkerTurret, netname, string, "walker");
16 /* fullname   */ ATTRIB(WalkerTurret, turret_name, string, _("Walker Turret"));
17     ATTRIB(WalkerTurret, m_weapon, Weapon, WEP_WALKER);
18 ENDCLASS(WalkerTurret)
19 REGISTER_TURRET(WALKER, NEW(WalkerTurret));
20
21 #endif
22
23 #ifdef IMPLEMENTATION
24
25 #include "walker_weapon.qc"
26
27 #ifdef SVQC
28
29 float autocvar_g_turrets_unit_walker_melee_damage;
30 float autocvar_g_turrets_unit_walker_melee_force;
31 float autocvar_g_turrets_unit_walker_melee_range;
32 float autocvar_g_turrets_unit_walker_rocket_damage;
33 float autocvar_g_turrets_unit_walker_rocket_radius;
34 float autocvar_g_turrets_unit_walker_rocket_force;
35 float autocvar_g_turrets_unit_walker_rocket_speed;
36 float autocvar_g_turrets_unit_walker_rocket_range;
37 float autocvar_g_turrets_unit_walker_rocket_range_min;
38 float autocvar_g_turrets_unit_walker_rocket_refire;
39 float autocvar_g_turrets_unit_walker_rocket_turnrate;
40 float autocvar_g_turrets_unit_walker_speed_stop;
41 float autocvar_g_turrets_unit_walker_speed_walk;
42 float autocvar_g_turrets_unit_walker_speed_run;
43 float autocvar_g_turrets_unit_walker_speed_jump;
44 float autocvar_g_turrets_unit_walker_speed_swim;
45 float autocvar_g_turrets_unit_walker_speed_roam;
46 float autocvar_g_turrets_unit_walker_turn;
47 float autocvar_g_turrets_unit_walker_turn_walk;
48 float autocvar_g_turrets_unit_walker_turn_strafe;
49 float autocvar_g_turrets_unit_walker_turn_swim;
50 float autocvar_g_turrets_unit_walker_turn_run;
51
52 const int ANIM_NO         = 0;
53 const int ANIM_TURN       = 1;
54 const int ANIM_WALK       = 2;
55 const int ANIM_RUN        = 3;
56 const int ANIM_STRAFE_L   = 4;
57 const int ANIM_STRAFE_R   = 5;
58 const int ANIM_JUMP       = 6;
59 const int ANIM_LAND       = 7;
60 const int ANIM_PAIN       = 8;
61 const int ANIM_MELEE      = 9;
62 const int ANIM_SWIM       = 10;
63 const int ANIM_ROAM       = 11;
64
65 .float animflag;
66 .float idletime;
67
68 #define WALKER_PATH(s,e) pathlib_astar(s,e)
69
70 float walker_firecheck()
71 {SELFPARAM();
72     if (self.animflag == ANIM_MELEE)
73         return 0;
74
75     return turret_firecheck();
76 }
77
78 void walker_melee_do_dmg()
79 {SELFPARAM();
80     vector where;
81     entity e;
82
83     makevectors(self.angles);
84     where = self.origin + v_forward * 128;
85
86     e = findradius(where,32);
87     while (e)
88     {
89         if (turret_validate_target(self, e, self.target_validate_flags))
90             if (e != self && e.owner != self)
91                 Damage(e, self, self, (autocvar_g_turrets_unit_walker_melee_damage), DEATH_TURRET_WALK_MELEE.m_id, '0 0 0', v_forward * (autocvar_g_turrets_unit_walker_melee_force));
92
93         e = e.chain;
94     }
95 }
96
97 void walker_setnoanim()
98 {SELFPARAM();
99     turrets_setframe(ANIM_NO, false);
100     self.animflag = self.frame;
101 }
102 void walker_rocket_explode()
103 {SELFPARAM();
104     RadiusDamage (self, self.owner, (autocvar_g_turrets_unit_walker_rocket_damage), 0, (autocvar_g_turrets_unit_walker_rocket_radius), self, world, (autocvar_g_turrets_unit_walker_rocket_force), DEATH_TURRET_WALK_ROCKET.m_id, world);
105     remove (self);
106 }
107
108 void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
109 {SELFPARAM();
110     self.health = self.health - damage;
111     self.velocity = self.velocity + vforce;
112
113     if (self.health <= 0)
114         W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
115 }
116
117 #define WALKER_ROCKET_MOVE movelib_move_simple(newdir, (autocvar_g_turrets_unit_walker_rocket_speed), (autocvar_g_turrets_unit_walker_rocket_turnrate)); UpdateCSQCProjectile(self)
118 void walker_rocket_loop();
119 void walker_rocket_think()
120 {SELFPARAM();
121     vector newdir;
122     float edist;
123     float itime;
124     float m_speed;
125
126     self.nextthink = time;
127
128     edist = vlen(self.enemy.origin - self.origin);
129
130     // Simulate crude guidance
131     if (self.cnt < time)
132     {
133         if (edist < 1000)
134             self.tur_shotorg = randomvec() * min(edist, 64);
135         else
136             self.tur_shotorg = randomvec() * min(edist, 256);
137
138         self.cnt = time + 0.5;
139     }
140
141     if (edist < 128)
142         self.tur_shotorg = '0 0 0';
143
144     if (self.max_health < time)
145     {
146         self.think        = walker_rocket_explode;
147         self.nextthink  = time;
148         return;
149     }
150
151     if (self.shot_dmg != 1337 && random() < 0.01)
152     {
153         walker_rocket_loop();
154         return;
155     }
156
157     m_speed = vlen(self.velocity);
158
159     // Enemy dead? just keep on the current heading then.
160     if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
161         self.enemy = world;
162
163     if (self.enemy)
164     {
165         itime = max(edist / m_speed, 1);
166         newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
167     }
168     else
169         newdir  = normalize(self.velocity);
170
171     WALKER_ROCKET_MOVE;
172 }
173
174 void walker_rocket_loop3()
175 {SELFPARAM();
176     vector newdir;
177     self.nextthink = time;
178
179     if (self.max_health < time)
180     {
181         self.think = walker_rocket_explode;
182         return;
183     }
184
185     if (vlen(self.origin - self.tur_shotorg) < 100 )
186     {
187         self.think = walker_rocket_think;
188         return;
189     }
190
191     newdir = steerlib_pull(self.tur_shotorg);
192     WALKER_ROCKET_MOVE;
193
194     self.angles = vectoangles(self.velocity);
195 }
196
197 void walker_rocket_loop2()
198 {SELFPARAM();
199     vector newdir;
200
201     self.nextthink = time;
202
203     if (self.max_health < time)
204     {
205         self.think = walker_rocket_explode;
206         return;
207     }
208
209     if (vlen(self.origin - self.tur_shotorg) < 100 )
210     {
211         self.tur_shotorg = self.origin - '0 0 200';
212         self.think = walker_rocket_loop3;
213         return;
214     }
215
216     newdir = steerlib_pull(self.tur_shotorg);
217     WALKER_ROCKET_MOVE;
218 }
219
220 void walker_rocket_loop()
221 {SELFPARAM();
222     self.nextthink = time;
223     self.tur_shotorg = self.origin + '0 0 300';
224     self.think = walker_rocket_loop2;
225     self.shot_dmg = 1337;
226 }
227
228 void walker_fire_rocket(vector org)
229 {SELFPARAM();
230     entity rocket;
231
232     fixedmakevectors(self.angles);
233
234     te_explosion (org);
235
236     rocket = spawn ();
237     setorigin(rocket, org);
238
239     sound (self, CH_WEAPON_A, SND_HAGAR_FIRE, VOL_BASE, ATTEN_NORM);
240     setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
241
242     rocket.classname              = "walker_rocket";
243     rocket.owner                          = self;
244     rocket.bot_dodge              = true;
245     rocket.bot_dodgerating      = 50;
246     rocket.takedamage            = DAMAGE_YES;
247     rocket.damageforcescale   = 2;
248     rocket.health                        = 25;
249     rocket.tur_shotorg          = randomvec() * 512;
250     rocket.cnt                          = time + 1;
251     rocket.enemy                          = self.enemy;
252
253     if (random() < 0.01)
254         rocket.think              = walker_rocket_loop;
255     else
256         rocket.think              = walker_rocket_think;
257
258     rocket.event_damage    = walker_rocket_damage;
259
260     rocket.nextthink              = time;
261     rocket.movetype                = MOVETYPE_FLY;
262     rocket.velocity                = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * (autocvar_g_turrets_unit_walker_rocket_speed);
263     rocket.angles                        = vectoangles(rocket.velocity);
264     rocket.touch                          = walker_rocket_explode;
265     rocket.flags                          = FL_PROJECTILE;
266     rocket.solid                          = SOLID_BBOX;
267     rocket.max_health            = time + 9;
268     rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
269
270     CSQCProjectile(rocket, false, PROJECTILE_ROCKET, false); // no culling, has fly sound
271 }
272
273 .vector enemy_last_loc;
274 .float enemy_last_time;
275 void walker_move_to(vector _target, float _dist)
276 {SELFPARAM();
277     switch (self.waterlevel)
278     {
279         case WATERLEVEL_NONE:
280             if (_dist > 500)
281                 self.animflag = ANIM_RUN;
282             else
283                 self.animflag = ANIM_WALK;
284         case WATERLEVEL_WETFEET:
285         case WATERLEVEL_SWIMMING:
286             if (self.animflag != ANIM_SWIM)
287                 self.animflag = ANIM_WALK;
288             else
289                 self.animflag = ANIM_SWIM;
290             break;
291         case WATERLEVEL_SUBMERGED:
292             self.animflag = ANIM_SWIM;
293     }
294
295     self.moveto = _target;
296     self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
297
298     if(self.enemy)
299     {
300         self.enemy_last_loc = _target;
301         self.enemy_last_time = time;
302     }
303 }
304
305 void walker_move_path()
306 {SELFPARAM();
307 #ifdef WALKER_FANCYPATHING
308     // Are we close enougth to a path node to switch to the next?
309     if (vlen(self.origin  - self.pathcurrent.origin) < 64)
310         if (self.pathcurrent.path_next == world)
311         {
312             // Path endpoint reached
313             pathlib_deletepath(self.pathcurrent.owner);
314             self.pathcurrent = world;
315
316             if (self.pathgoal)
317             {
318                 if (self.pathgoal.use)
319                     self.pathgoal.use();
320
321                 if (self.pathgoal.enemy)
322                 {
323                     self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
324                     self.pathgoal = self.pathgoal.enemy;
325                 }
326             }
327             else
328                 self.pathgoal = world;
329         }
330         else
331             self.pathcurrent = self.pathcurrent.path_next;
332
333     self.moveto = self.pathcurrent.origin;
334     self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
335     walker_move_to(self.moveto, 0);
336
337 #else
338     if (vlen(self.origin - self.pathcurrent.origin) < 64)
339         self.pathcurrent = self.pathcurrent.enemy;
340
341     if(!self.pathcurrent)
342         return;
343
344     self.moveto = self.pathcurrent.origin;
345     self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
346     walker_move_to(self.moveto, 0);
347 #endif
348 }
349
350 spawnfunc(turret_walker) { if(!turret_initialize(TUR_WALKER)) remove(self); }
351
352         METHOD(WalkerTurret, tr_think, void(WalkerTurret thistur))
353         {
354             fixedmakevectors(self.angles);
355
356             if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
357                 walker_move_path();
358             else if (self.enemy == world)
359             {
360                 if(self.pathcurrent)
361                     walker_move_path();
362                 else
363                 {
364                     if(self.enemy_last_time != 0)
365                     {
366                         if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
367                             self.enemy_last_time = 0;
368                         else
369                             walker_move_to(self.enemy_last_loc, 0);
370                     }
371                     else
372                     {
373                         if(self.animflag != ANIM_NO)
374                         {
375                             traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
376
377                             if(trace_fraction != 1.0)
378                                 self.tur_head.idletime = -1337;
379                             else
380                             {
381                                 traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
382                                 if(trace_fraction == 1.0)
383                                     self.tur_head.idletime = -1337;
384                             }
385
386                             if(self.tur_head.idletime == -1337)
387                             {
388                                 self.moveto = self.origin + randomvec() * 256;
389                                 self.tur_head.idletime = 0;
390                             }
391
392                             self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
393                             self.moveto_z = self.origin_z + 64;
394                             walker_move_to(self.moveto, 0);
395                         }
396
397                         if(self.idletime < time)
398                         {
399                             if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
400                             {
401                                 self.idletime = time + 1 + random() * 5;
402                                 self.moveto = self.origin;
403                                 self.animflag = ANIM_NO;
404                             }
405                             else
406                             {
407                                 self.animflag = ANIM_WALK;
408                                 self.idletime = time + 4 + random() * 2;
409                                 self.moveto = self.origin + randomvec() * 256;
410                                 self.tur_head.moveto = self.moveto;
411                                 self.tur_head.idletime = 0;
412                             }
413                         }
414                     }
415                 }
416             }
417             else
418             {
419                 if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_melee_range) && self.animflag != ANIM_MELEE)
420                 {
421                     vector wish_angle;
422
423                     wish_angle = angleofs(self, self.enemy);
424                     if (self.animflag != ANIM_SWIM)
425                     if (fabs(wish_angle_y) < 15)
426                     {
427                         self.moveto   = self.enemy.origin;
428                         self.steerto  = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
429                         self.animflag = ANIM_MELEE;
430                     }
431                 }
432                 else if (self.tur_head.attack_finished_single < time)
433                 {
434                     if(self.tur_head.shot_volly)
435                     {
436                         self.animflag = ANIM_NO;
437
438                         self.tur_head.shot_volly = self.tur_head.shot_volly -1;
439                         if(self.tur_head.shot_volly == 0)
440                             self.tur_head.attack_finished_single = time + (autocvar_g_turrets_unit_walker_rocket_refire);
441                         else
442                             self.tur_head.attack_finished_single = time + 0.2;
443
444                         if(self.tur_head.shot_volly > 1)
445                             walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
446                         else
447                             walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
448                     }
449                     else
450                     {
451                         if (self.tur_dist_enemy > (autocvar_g_turrets_unit_walker_rocket_range_min))
452                         if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_rocket_range))
453                             self.tur_head.shot_volly = 4;
454                     }
455                 }
456                 else
457                 {
458                     if (self.animflag != ANIM_MELEE)
459                         walker_move_to(self.enemy.origin, self.tur_dist_enemy);
460                 }
461             }
462
463             {
464                 vector real_angle;
465                 float turny = 0, turnx = 0;
466                 float vz;
467
468                 real_angle = vectoangles(self.steerto) - self.angles;
469                 vz = self.velocity_z;
470
471                 switch (self.animflag)
472                 {
473                     case ANIM_NO:
474                         movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
475                         break;
476
477                     case ANIM_TURN:
478                         turny = (autocvar_g_turrets_unit_walker_turn);
479                         movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
480                         break;
481
482                     case ANIM_WALK:
483                         turny = (autocvar_g_turrets_unit_walker_turn_walk);
484                         movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_walk), 0.6);
485                         break;
486
487                     case ANIM_RUN:
488                         turny = (autocvar_g_turrets_unit_walker_turn_run);
489                         movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_run), 0.6);
490                         break;
491
492                     case ANIM_STRAFE_L:
493                         turny = (autocvar_g_turrets_unit_walker_turn_strafe);
494                         movelib_move_simple(v_right * -1, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
495                         break;
496
497                     case ANIM_STRAFE_R:
498                         turny = (autocvar_g_turrets_unit_walker_turn_strafe);
499                         movelib_move_simple(v_right, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
500                         break;
501
502                     case ANIM_JUMP:
503                         self.velocity += '0 0 1' * (autocvar_g_turrets_unit_walker_speed_jump);
504                         break;
505
506                     case ANIM_LAND:
507                         break;
508
509                     case ANIM_PAIN:
510                         if(self.frame != ANIM_PAIN)
511                             defer(0.25, walker_setnoanim);
512
513                         break;
514
515                     case ANIM_MELEE:
516                         if(self.frame != ANIM_MELEE)
517                         {
518                             defer(0.41, walker_setnoanim);
519                             defer(0.21, walker_melee_do_dmg);
520                         }
521
522                         movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
523                         break;
524
525                     case ANIM_SWIM:
526                         turny = (autocvar_g_turrets_unit_walker_turn_swim);
527                         turnx = (autocvar_g_turrets_unit_walker_turn_swim);
528
529                         self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
530                         movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_swim), 0.3);
531                         vz = self.velocity_z + sin(time * 4) * 8;
532                         break;
533
534                     case ANIM_ROAM:
535                         turny = (autocvar_g_turrets_unit_walker_turn_walk);
536                         movelib_move_simple(v_forward ,(autocvar_g_turrets_unit_walker_speed_roam), 0.5);
537                         break;
538                 }
539
540                 if(turny)
541                 {
542                     turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny );
543                     self.angles_y += turny;
544                 }
545
546                 if(turnx)
547                 {
548                     turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx );
549                     self.angles_x += turnx;
550                 }
551
552                 self.velocity_z = vz;
553             }
554
555
556             if(self.origin != self.oldorigin)
557                 self.SendFlags |= TNSF_MOVE;
558
559             self.oldorigin = self.origin;
560             turrets_setframe(self.animflag, false);
561         }
562         METHOD(WalkerTurret, tr_death, void(WalkerTurret this, entity it))
563         {
564 #ifdef WALKER_FANCYPATHING
565             if (it.pathcurrent)
566                 pathlib_deletepath(it.pathcurrent.owner);
567 #endif
568             it.pathcurrent = NULL;
569         }
570         METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it))
571         {
572             it.ticrate = 0.05;
573
574             entity e;
575
576             // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
577             if(it.movetype == MOVETYPE_WALK)
578             {
579                 if(it.pos1)
580                     setorigin(it, it.pos1);
581                 if(it.pos2)
582                     it.angles = it.pos2;
583             }
584
585             it.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
586             it.aim_flags = TFL_AIM_LEAD;
587             it.turret_flags |= TUR_FLAG_HITSCAN;
588
589             it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
590             it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
591             it.iscreature = true;
592             it.teleportable = TELEPORT_NORMAL;
593             it.damagedbycontents = true;
594             it.solid = SOLID_SLIDEBOX;
595             it.takedamage = DAMAGE_AIM;
596             if(it.movetype != MOVETYPE_WALK)
597             {
598                 setorigin(it, it.origin);
599                 tracebox(it.origin + '0 0 128', it.mins, it.maxs, it.origin - '0 0 10000', MOVE_NORMAL, it);
600                 setorigin(it, trace_endpos + '0 0 4');
601                 it.pos1 = it.origin;
602                 it.pos2 = it.angles;
603             }
604             it.movetype = MOVETYPE_WALK;
605             it.idle_aim = '0 0 0';
606             it.turret_firecheckfunc = walker_firecheck;
607
608             if (it.target != "")
609             {
610                 e = find(world, targetname, it.target);
611                 if (!e)
612                 {
613                     LOG_TRACE("Initital waypoint for walker does NOT exsist, fix your map!\n");
614                     it.target = "";
615                 }
616
617                 if (e.classname != "turret_checkpoint")
618                     LOG_TRACE("Warning: not a turrret path\n");
619                 else
620                 {
621 #ifdef WALKER_FANCYPATHING
622                     it.pathcurrent = WALKER_PATH(it.origin, e.origin);
623                     it.pathgoal = e;
624 #else
625                     it.pathcurrent = e;
626 #endif
627                 }
628             }
629         }
630
631 #endif // SVQC
632 #ifdef CSQC
633
634 #include "../../../client/movelib.qh"
635
636 void walker_draw(entity this)
637 {
638     float dt;
639
640     dt = time - self.move_time;
641     self.move_time = time;
642     if(dt <= 0)
643         return;
644
645     fixedmakevectors(self.angles);
646     movelib_groundalign4point(300, 100, 0.25, 45);
647     setorigin(self, self.origin + self.velocity * dt);
648     self.tur_head.angles += dt * self.tur_head.move_avelocity;
649     self.angles_y = self.move_angles_y;
650
651     if (self.health < 127)
652     if(random() < 0.15)
653         te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
654 }
655
656         METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it))
657         {
658             it.gravity          = 1;
659             it.movetype         = MOVETYPE_BOUNCE;
660             it.move_movetype    = MOVETYPE_BOUNCE;
661             it.move_origin      = it.origin;
662             it.move_time                = time;
663             it.draw                     = walker_draw;
664         }
665
666 #endif // CSQC
667 #endif