]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/monsters/monster/zombie.qc
Fix some weird problems with zombie movement, fix spawner not spawning monsters
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / monsters / monster / zombie.qc
index 108deed0056f036400cc76105f2392706d339912..ff73c8efa4a1313dd7763fcf9a57d73609dec901 100644 (file)
@@ -2,7 +2,6 @@
  * Special purpose fields:
  * .delay - time at which to check if zombie's enemy is still in range
  * .enemy - enemy of this zombie
- * .state - state of the zombie, see ZOMBIE_STATE_*
  */
  
 // cvars
@@ -11,17 +10,12 @@ float autocvar_g_monster_zombie_stopspeed;
 float autocvar_g_monster_zombie_attack_leap_damage;
 float autocvar_g_monster_zombie_attack_leap_delay;
 float autocvar_g_monster_zombie_attack_leap_force;
-float autocvar_g_monster_zombie_attack_leap_range;
 float autocvar_g_monster_zombie_attack_leap_speed;
 float autocvar_g_monster_zombie_attack_stand_damage;
 float autocvar_g_monster_zombie_attack_stand_delay;
-float autocvar_g_monster_zombie_attack_stand_range;
 float autocvar_g_monster_zombie_health;
-float autocvar_g_monster_zombie_idle_timer;
 float autocvar_g_monster_zombie_speed_walk;
 float autocvar_g_monster_zombie_speed_run;
-float autocvar_g_monster_zombie_target_recheck_delay;
-float autocvar_g_monster_zombie_target_range;
 
 // zombie animations
 #define zombie_anim_attackleap                 0
@@ -59,11 +53,6 @@ float autocvar_g_monster_zombie_target_range;
 const vector ZOMBIE_MIN                                 = '-18 -18 -25';
 const vector ZOMBIE_MAX                                 = '18 18 47';
 
-#define ZOMBIE_STATE_SPAWNING          0
-#define ZOMBIE_STATE_IDLE                      1
-#define ZOMBIE_STATE_ANGRY                     2
-#define ZOMBIE_STATE_ATTACK_LEAP       3
-
 void zombie_spawn();
 void spawnfunc_monster_zombie();
 void zombie_think();
@@ -123,11 +112,12 @@ void zombie_attack_standing()
                self.frame = zombie_anim_attackstanding3;
 
        self.nextthink = time + autocvar_g_monster_zombie_attack_stand_delay;
+       self.attack_finished_single = self.nextthink;
 }
 
 void zombie_attack_leap_touch()
 {
-       vector angles_face = '0 0 0';
+       vector angles_face;
        float bigdmg = autocvar_g_monster_zombie_attack_leap_damage * self.scale;
        
        if (other.deadflag != DEAD_NO)
@@ -145,130 +135,25 @@ void zombie_attack_leap_touch()
        angles_face = vectoangles(self.moveto - self.origin);
        angles_face = normalize(angles_face) * autocvar_g_monster_zombie_attack_leap_force;
        Damage(other, self, self, bigdmg * monster_skill, DEATH_MONSTER_MELEE, trace_endpos, angles_face);      
-
-       // make this guy zombie's priority if it wasn't already
-       if (other.deadflag == DEAD_NO)
-       if (self.enemy != other)
-               self.enemy = other;
                
        self.touch = MonsterTouch;
 }
 
-void zombie_attack_leap()
+float zombie_attack_ranged()
 {
-       vector angles_face = '0 0 0', vel = '0 0 0';
-
-       // face the enemy       
-       self.state = ZOMBIE_STATE_ATTACK_LEAP;
-       self.frame = zombie_anim_attackleap;
-       angles_face = vectoangles(self.enemy.origin - self.origin);
-       self.angles_y = angles_face_y ;
-       self.nextthink = time + autocvar_g_monster_zombie_attack_leap_delay;
-       self.touch = zombie_attack_leap_touch;
        makevectors(self.angles);
-       vel = normalize(v_forward);
-       self.velocity = vel * autocvar_g_monster_zombie_attack_leap_speed;
+       if(monster_leap(zombie_anim_attackleap, zombie_attack_leap_touch, v_forward * autocvar_g_monster_zombie_attack_leap_speed + '0 0 200', autocvar_g_monster_zombie_attack_leap_delay))
+               return TRUE;
+               
+       return FALSE;
 }
 
 void zombie_think()
 {
-       float finished = FALSE, enemyDistance = 0, mySpeed = 0;
-       
        self.think = zombie_think;
-       
-       if (self.state == ZOMBIE_STATE_ATTACK_LEAP) {
-               // reset to angry
-               self.state = ZOMBIE_STATE_ANGRY;
-               self.touch = func_null;
-       }
-       
-       if (self.state == ZOMBIE_STATE_SPAWNING) {
-               // become idle when zombie spawned
-               self.frame = zombie_anim_idle;
-               self.state = ZOMBIE_STATE_IDLE;
-       }
-       
-       if(self.enemy && !monster_isvalidtarget(self.enemy, self, FALSE))
-               self.enemy = world;
-       
-       if (self.enemy)
-       if (self.enemy.team == self.team || self.monster_owner == self.enemy)
-               self.enemy = world;
-       
-       if(teamplay && autocvar_g_monsters_teams && self.monster_owner.team != self.team)
-               self.monster_owner = world;     
-       
-       // remove enemy that ran away
-       if (self.enemy)
-       if (self.delay <= time) // check if we can do the rescan now
-       if (vlen(self.origin - self.enemy.origin) > autocvar_g_monster_zombie_target_range * self.scale) 
-       {
-               //print("removing enemy, he is too far: ", ftos(vlen(self.origin - self.enemy.origin)), "\n");
-               //print("delay was ", ftos(self.delay), "\n");
-               self.enemy = world;
-       } 
-       else
-               self.delay = time + autocvar_g_monster_zombie_target_recheck_delay;
-       
-       // find an enemy if no enemy available
-       if not(self.enemy) 
-       {
-               self.enemy = FindTarget(self);
-               if (self.enemy)
-                       self.delay = time + autocvar_g_monster_zombie_target_recheck_delay;
-       }
-
-       if (self.enemy) 
-       {
-               // make sure zombie is angry
-               self.state = ZOMBIE_STATE_ANGRY;
-               
-
-               // this zombie has an enemy, attack if close enough, go to it if not!
-               traceline(self.origin, self.enemy.origin, FALSE, self);
-               enemyDistance = vlen(trace_endpos - self.origin);
-               mySpeed = vlen(self.velocity);
-               
-               //print("speed ", ftos(mySpeed), "\n");
-               
-               if (trace_ent == self.enemy)
-               if (self.enemy.deadflag == DEAD_NO)
-               if (mySpeed <= 30)
-                       if (enemyDistance <= autocvar_g_monster_zombie_attack_stand_range * self.scale) 
-                       {
-                               //RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)
-                               zombie_attack_standing();
-                               finished = TRUE;
-                       } 
-                       else if (enemyDistance <= autocvar_g_monster_zombie_attack_leap_range * self.scale) 
-                       {
-                               // do attackleap (set yaw, velocity, and check do damage on the first player entity it touches)
-                               zombie_attack_leap();
-                               finished = TRUE;
-                       }
-               
-       }
-       
-       self.nextthink = time + 1;
+       self.nextthink = time + 0.3;
 
-       if not(finished) 
-       {
-               monster_move(autocvar_g_monster_zombie_speed_run, autocvar_g_monster_zombie_speed_walk, autocvar_g_monster_zombie_stopspeed, zombie_anim_runforward, zombie_anim_runforward, zombie_anim_idle);
-               
-               if (self.enemy || self.monster_owner)
-               {
-                       self.nextthink = time + 0.1;
-                       return;
-               }   
-       }
-       
-       if not(self.enemy || self.monster_owner || self.goalentity) 
-       {
-               // stay idle
-               //print("zombie is idling while waiting for some fresh meat...\n");
-               self.frame = ((mySpeed <= 20) ? zombie_anim_idle : zombie_anim_runforward);
-               self.nextthink = time + autocvar_g_monster_zombie_idle_timer * random();        
-       }
+       monster_move(autocvar_g_monster_zombie_speed_run, autocvar_g_monster_zombie_speed_walk, autocvar_g_monster_zombie_stopspeed, zombie_anim_runforward, zombie_anim_runforward, zombie_anim_idle);
 }
 
 void zombie_spawn() 
@@ -279,10 +164,12 @@ void zombie_spawn()
        self.classname                  = "monster_zombie";
        self.nextthink                  = time + 2.1;
        self.pain_finished      = self.nextthink;
-       self.state                              = ZOMBIE_STATE_SPAWNING;
        self.frame                              = zombie_anim_spawn;
        self.think                              = zombie_think;
        self.sprite_height      = 50 * self.scale;
+       self.checkattack                = GenericCheckAttack;
+       self.attack_melee               = zombie_attack_standing;
+       self.attack_ranged              = zombie_attack_ranged;
        self.skin                               = rint(random() * 4);
        
        monster_hook_spawn(); // for post-spawn mods