monster_zombie (not enabled by default, -DMONSTES_ENABLED to enable)
authortzork <tzork@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Wed, 4 Nov 2009 13:37:21 +0000 (13:37 +0000)
committertzork <tzork@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Wed, 4 Nov 2009 13:37:21 +0000 (13:37 +0000)
git-svn-id: svn://svn.icculus.org/nexuiz/trunk@8209 f962a42d-fe04-0410-a3ab-8c8b0445ebaa

data/models/monsters/zombie.dpm [new file with mode: 0644]
data/models/monsters/zombie.dpm.framegroups [new file with mode: 0644]
data/qcsrc/server/monsters/monster_zombie.qc [new file with mode: 0644]
data/qcsrc/server/progs.src

diff --git a/data/models/monsters/zombie.dpm b/data/models/monsters/zombie.dpm
new file mode 100644 (file)
index 0000000..8a7ca02
Binary files /dev/null and b/data/models/monsters/zombie.dpm differ
diff --git a/data/models/monsters/zombie.dpm.framegroups b/data/models/monsters/zombie.dpm.framegroups
new file mode 100644 (file)
index 0000000..4bd49bd
--- /dev/null
@@ -0,0 +1,31 @@
+1 56 30 0      // zombie attackleap         1\r
+57 41 60 1     // zombie attackrun1         2\r
+98 41 60 1     // zombie attackrun2         3\r
+139 41 60 1    // zombie attackrun3         4\r
+180 41 30 1    // zombie attackstanding1    5\r
+221 35 30 1    // zombie attackstanding2    6\r
+256 41 30 1    // zombie attackstanding3    7\r
+297 21 60 1    // zombie blockend           8\r
+318 21 60 0    // zombie blockstart         9\r
+339 96 30 0    // zombie deathback1         10\r
+435 67 30 0    // zombie deathback2         11\r
+502 71 30 0    // zombie deathback3         12\r
+573 61 30 0    // zombie deathfront1        13\r
+634 66 30 0    // zombie deathfront2        14\r
+700 96 30 0    // zombie deathfront3        15\r
+796 96 30 0    // zombie deathleft1         16\r
+892 71 30 0    // zombie deathleft2         17\r
+963 66 30 0    // zombie deathright1        18\r
+1029 86  30 0  // zombie deathright2        19\r
+1115 121 10 1  // zombie idle               20\r
+1236 11 30 0   // zombie painback1          21\r
+1247 11 30 0   // zombie painback2          22\r
+1258 11 30 0   // zombie painfront1         23\r
+1269 11 30 0   // zombie painfront2         24\r
+1280 41 60 1   // zombie runbackwards       25\r
+1321 41 60 1   // zombie runbackwardsleft   26\r
+1362 41 60 1   // zombie runbackwardsright  27\r
+1403 41 60 1   // zombie runforward         28\r
+1444 41 60 1   // zombie runforwardleft     29\r
+1485 41 60 1   // zombie runforwardright    30\r
+1526 61 30 0   // zombie spawn              31\r
diff --git a/data/qcsrc/server/monsters/monster_zombie.qc b/data/qcsrc/server/monsters/monster_zombie.qc
new file mode 100644 (file)
index 0000000..0d43660
--- /dev/null
@@ -0,0 +1,555 @@
+//#define MONSTES_ENABLED\r
+#ifdef MONSTES_ENABLED\r
+\r
+#define zombie_anim_attackleap         0\r
+#define zombie_anim_attackrun1         1\r
+#define zombie_anim_attackrun2         2\r
+#define zombie_anim_attackrun3         3\r
+#define zombie_anim_attackstanding1    4\r
+#define zombie_anim_attackstanding2    5\r
+#define zombie_anim_attackstanding3    6\r
+#define zombie_anim_blockend           7\r
+#define zombie_anim_blockstart         8\r
+#define zombie_anim_deathback1         9\r
+#define zombie_anim_deathback2         10\r
+#define zombie_anim_deathback3         11\r
+#define zombie_anim_deathfront1        12\r
+#define zombie_anim_deathfront2        13\r
+#define zombie_anim_deathfront3        14\r
+#define zombie_anim_deathleft1         15\r
+#define zombie_anim_deathleft2         16\r
+#define zombie_anim_deathright1        17\r
+#define zombie_anim_deathright2        18\r
+#define zombie_anim_idle               19\r
+#define zombie_anim_painback1          20\r
+#define zombie_anim_painback2          21\r
+#define zombie_anim_painfront1         22\r
+#define zombie_anim_painfront2         23\r
+#define zombie_anim_runbackwards       24\r
+#define zombie_anim_runbackwardsleft   25\r
+#define zombie_anim_runbackwardsright  26\r
+#define zombie_anim_runforward         27\r
+#define zombie_anim_runforwardleft     28\r
+#define zombie_anim_runforwardright    29\r
+#define zombie_anim_spawn              30\r
+\r
+#define ZOMBIE_MIN                                      '-18 -18 -25'\r
+#define ZOMBIE_MAX                                      '18 18 47'\r
+\r
+#define ZV_IDLE     10\r
+\r
+#define ZV_PATH     100\r
+#define ZV_HUNT     200\r
+\r
+#define ZV_ATTACK_FIND  10\r
+#define ZV_ATTACK_RUN   20\r
+#define ZV_ATTACK_STAND 30\r
+\r
+#define ZV_PATH2 10000\r
+\r
+//.entity verbs_idle;\r
+//.entity verbs_attack;\r
+//.entity verbs_move;\r
+\r
+//.float  state_timeout;\r
+//.void() monster_state;\r
+#define MONSTERFLAG_NORESPAWN 2\r
+\r
+void zombie_spawn();\r
+\r
+float zombie_scoretarget(entity trg)\r
+{\r
+    float  tmp;\r
+    vector ang1;\r
+\r
+    if (trg.takedamage == DAMAGE_AIM)\r
+    if not (trg.flags & FL_NOTARGET)\r
+    if (trg.deadflag == DEAD_NO)\r
+    if (trg.team != self.team)\r
+    {\r
+        if((self.origin_z - trg.origin_z) < 128)\r
+        {\r
+            ang1 = normalize(self.origin - trg.origin);\r
+            tmp = vlen(ang1 - v_forward);\r
+            if(tmp > 1.5)\r
+            {\r
+                traceline(self.origin + '0 0 47',trg.origin + '0 0 32',MOVE_NORMAL,self);\r
+                if(trace_ent != trg)\r
+                    return 0;\r
+\r
+                return (cvar("g_monster_zombie_targetrange") - vlen(self.origin - trg.origin)) * tmp;\r
+            }\r
+            else if(self.enemy == trg)\r
+                return (cvar("g_monster_zombie_targetrange") - vlen(self.origin - trg.origin)) * tmp;\r
+        }\r
+    }\r
+\r
+    return 0;\r
+}\r
+\r
+void zombie_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
+{\r
+    //dprint("zombie_corpse_damage\n");\r
+    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);\r
+\r
+    self.health -= damage;\r
+\r
+    if(self.health < 0)\r
+    {\r
+        Violence_GibSplash(self, 1, 1, attacker);\r
+        remove(self);\r
+    }\r
+}\r
+\r
+void zombie_die(vector dir)\r
+{\r
+    vector v;\r
+    float f;\r
+\r
+    entity dummy;\r
+\r
+    dummy = spawn();\r
+    setmodel(dummy,"models/monsters/zombie.dpm");\r
+    setorigin(dummy, self.origin);\r
+    dummy.velocity  = self.velocity;\r
+    dummy.movetype  = MOVETYPE_BOUNCE;\r
+    dummy.think     = SUB_Remove;\r
+    dummy.nextthink = time + 3;\r
+    dummy.health    = 50;\r
+    dummy.takedamage = DAMAGE_YES;\r
+    dummy.event_damage = zombie_corpse_damage;\r
+    dummy.solid      = SOLID_CORPSE;\r
+    setsize(dummy,self.mins,self.maxs);\r
+\r
+    SUB_SetFade(dummy,time + 5,2);\r
+\r
+\r
+    v = normalize(self.origin - dir);\r
+    f = vlen(v_forward - v) - 1;\r
+    if(f > 0.5)\r
+        dummy.frame = zombie_anim_deathfront1 + rint(random() * 2);\r
+    else if(f < 0.5)\r
+        dummy.frame = zombie_anim_deathback1 + rint(random() * 2);\r
+    else\r
+    {\r
+        f = vlen(v_right - v) - 1;\r
+        if(f > 0.5)\r
+            dummy.frame = zombie_anim_deathright1 + rint(random() * 2);\r
+        else if(f < 0.5)\r
+            dummy.frame = zombie_anim_deathleft1 + rint(random() * 2);\r
+    }\r
+\r
+\r
+    if(self.spawnflags & MONSTERFLAG_NORESPAWN)\r
+    {\r
+        self.think = SUB_Remove;\r
+        self.nextthink = time;\r
+        return;\r
+    }\r
+\r
+    setmodel(self,"");\r
+    self.solid          = SOLID_NOT;\r
+    self.takedamage     = DAMAGE_NO;\r
+    self.event_damage   = SUB_Null;\r
+    self.enemy          = world;\r
+    self.think          = zombie_spawn;\r
+    self.nextthink      = time + cvar("g_monster_zombie_respawntime");\r
+    self.pain_finished  = self.nextthink;\r
+}\r
+\r
+void zombie_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
+{\r
+\r
+    vector v;\r
+    float f;\r
+\r
+    v = normalize(self.origin - hitloc);\r
+    f = vlen(v_forward - v) - 1;\r
+\r
+\r
+    self.health -= damage;\r
+    self.velocity = self.velocity + force;\r
+    if(self.health <= 0)\r
+    {\r
+        zombie_die(hitloc);\r
+        return;\r
+    }\r
+\r
+    Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);\r
+\r
+       if (damage > 50)\r
+               Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker);\r
+       if (damage > 100)\r
+               Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker);\r
+\r
+    if (time > self.pain_finished)\r
+    {\r
+        if(f < 0.5)\r
+        {\r
+            if(random() < 0.5)\r
+                self.frame = zombie_anim_painback1;\r
+            else\r
+                self.frame = zombie_anim_painback2;\r
+        }\r
+        else\r
+        {\r
+            if(random() < 0.5)\r
+                self.frame = zombie_anim_painfront1;\r
+            else\r
+                self.frame = zombie_anim_painfront2;\r
+        }\r
+\r
+        self.pain_finished = time + 0.36;\r
+    }\r
+}\r
+\r
+.vector bvec;\r
+.float bvec_time;\r
+\r
+void zombie_move()\r
+{\r
+    vector real_angle;\r
+    float vz, tdiff, tspeed;\r
+\r
+    tdiff = time - self.zoomstate;\r
+    tspeed = tdiff * cvar("g_monster_zombie_turnspeed");\r
+    vz = self.velocity_z;\r
+    self.zoomstate = time;\r
+\r
+    if(self.bvec_time < time)\r
+    {\r
+        self.bvec_time = time + 0.2;\r
+        self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64);\r
+    }\r
+\r
+    if(self.enemy)\r
+        self.moveto = self.enemy.origin;\r
+    else\r
+        self.moveto = self.origin + v_forward;\r
+\r
+    self.steerto = normalize(steerlib_attract2(self.moveto,0.5,500,0.95) + self.bvec);\r
+\r
+    self.angles_y = safeangle(self.angles_y);\r
+    real_angle = vectoangles(self.steerto) - self.angles;\r
+    self.angles_y += bound(-10, real_angle_y, 10);\r
+\r
+    if(vlen(self.origin - self.moveto) > 64)\r
+    {\r
+        movelib_move_simple(v_forward ,cvar("g_monster_zombie_movespeed"),0.6);\r
+        if(time > self.pain_finished)\r
+            if(self.attack_finished_single < time)\r
+                self.frame = zombie_anim_runforward;\r
+    }\r
+    else\r
+    {\r
+        movelib_beak_simple(cvar("g_monster_zombie_stopspeed"));\r
+        if(time > self.pain_finished)\r
+            if(self.attack_finished_single < time)\r
+                self.frame = zombie_anim_idle;\r
+    }\r
+\r
+    self.velocity_z = vz;\r
+    self.steerto = self.origin;\r
+}\r
+\r
+float zombie_verb_idle_roam(float eval)\r
+{\r
+    switch (eval)\r
+    {\r
+    case VCM_EVAL:\r
+\r
+        if(self.enemy)\r
+            return VS_CALL_NO;\r
+\r
+        return verb.verb_static_value;\r
+\r
+    case VCM_DO:\r
+\r
+        self.moveto = v_forward * 128;\r
+        self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64);\r
+\r
+        return VS_CALL_YES_DOING;\r
+    }\r
+\r
+    return VS_CALL_YES_DONE;\r
+}\r
+\r
+float zombie_verb_idle_stand(float eval)\r
+{\r
+    switch (eval)\r
+    {\r
+    case VCM_EVAL:\r
+\r
+        if(self.enemy)\r
+            return VS_CALL_NO;\r
+\r
+        return verb.verb_static_value;\r
+\r
+    case VCM_DO:\r
+\r
+        self.moveto   = self.origin;\r
+        self.frame    = zombie_anim_idle;\r
+        self.velocity = '0 0 0';\r
+\r
+        return VS_CALL_YES_DOING;\r
+    }\r
+\r
+    return VS_CALL_YES_DONE;\r
+}\r
+\r
+float zombie_verb_idle(float eval)\r
+{\r
+    switch (eval)\r
+    {\r
+    case VCM_EVAL:\r
+\r
+        if(self.enemy)\r
+            return VS_CALL_NO;\r
+\r
+        return verb.verb_static_value;\r
+\r
+    case VCM_DO:\r
+        float t;\r
+\r
+        t = cvar("g_monster_zombie_idle_timer_max") -  cvar("g_monster_zombie_idle_timer_min");\r
+        t = cvar("g_monster_zombie_idle_timer_min") + (random() * t);\r
+\r
+        if(random() < 0.5)\r
+            verbstack_push(self.verbs_idle, zombie_verb_idle_roam,  ZV_IDLE + 1, t, self);\r
+        else\r
+            verbstack_push(self.verbs_idle, zombie_verb_idle_stand, ZV_IDLE + 1, 0.1, self);\r
+\r
+        return VS_CALL_YES_DOING;\r
+    }\r
+\r
+    return VS_CALL_YES_DONE;\r
+}\r
+\r
+float zombie_verb_attack_findtarget(float eval)\r
+{\r
+    switch (eval)\r
+    {\r
+    case VCM_EVAL:\r
+        if(self.enemy)\r
+            return VS_CALL_NO;\r
+\r
+        return verb.verb_static_value;\r
+\r
+    case VCM_DO:\r
+\r
+        entity trg, best_trg;\r
+        float trg_score, best_trg_score;\r
+\r
+        trg = findradius(self.origin,cvar("g_monster_zombie_targetrange"));\r
+        while(trg)\r
+        {\r
+            trg_score = zombie_scoretarget(trg);\r
+            if(trg_score > best_trg_score)\r
+            {\r
+                best_trg = trg;\r
+                best_trg_score = trg_score;\r
+            }\r
+\r
+            trg = trg.chain;\r
+        }\r
+\r
+        if(best_trg)\r
+        {\r
+            self.enemy = best_trg;\r
+            dprint("Selected: ",best_trg.netname, " as target.\n");\r
+        }\r
+\r
+        return VS_CALL_YES_DOING;\r
+    }\r
+\r
+    return VS_CALL_YES_DONE;\r
+}\r
+\r
+void zombie_runattack_damage()\r
+{\r
+    entity oldself;\r
+    oldself = self;\r
+    self = self.owner;\r
+\r
+    if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_run_hitrange"))\r
+        return;\r
+\r
+    if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)\r
+        return;\r
+\r
+    Damage(self.enemy, self, self, cvar("g_monster_zombie_attack_run_damage"), DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin)  * cvar("g_monster_zombie_attack_run_force"));\r
+\r
+    self = oldself;\r
+    self.think = SUB_Remove;\r
+    self.nextthink = time;\r
+}\r
+\r
+float zombie_verb_attack_run(float eval)\r
+{\r
+    switch (eval)\r
+    {\r
+    case VCM_EVAL:\r
+        if not (self.enemy)\r
+            return VS_CALL_NO;\r
+\r
+        if(self.attack_finished_single > time)\r
+            return VS_CALL_NO;\r
+\r
+        if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_run_range"))\r
+            return VS_CALL_NO;\r
+\r
+        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)\r
+            return VS_CALL_NO;\r
+\r
+        return verb.verb_static_value;\r
+\r
+    case VCM_DO:\r
+        entity pain;\r
+        pain = spawn();\r
+        pain.owner = self;\r
+        pain.think = zombie_runattack_damage;\r
+        pain.nextthink = time + cvar("g_monster_zombie_attack_run_delay");\r
+\r
+        self.attack_finished_single = time + 0.7;\r
+        self.frame = zombie_anim_attackrun1 + rint(random() * 2);\r
+\r
+        return VS_CALL_YES_DOING;\r
+    }\r
+\r
+    return VS_CALL_YES_DONE;\r
+}\r
+\r
+void zombie_standattack_damage()\r
+{\r
+    //entity oldself;\r
+    //oldself = self;\r
+    //self = self.owner;\r
+\r
+    setorigin(self,self.owner.origin + v_forward * 32);\r
+    RadiusDamage(self, self.owner, cvar("g_monster_zombie_attack_stand_damage"),cvar("g_monster_zombie_attack_stand_damage"),16,self, cvar("g_monster_zombie_attack_stand_force"),DEATH_TURRET,world);\r
+    //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)\r
+\r
+\r
+    //self = oldself;\r
+    self.think = SUB_Remove;\r
+    self.nextthink = time;\r
+}\r
+\r
+float zombie_verb_attack_stand(float eval)\r
+{\r
+    switch (eval)\r
+    {\r
+    case VCM_EVAL:\r
+        if not (self.enemy)\r
+            return VS_CALL_NO;\r
+\r
+        if(self.attack_finished_single > time)\r
+            return VS_CALL_NO;\r
+\r
+        if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_stand_range"))\r
+            return VS_CALL_NO;\r
+\r
+        if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8)\r
+            return VS_CALL_NO;\r
+\r
+        return verb.verb_static_value;\r
+\r
+    case VCM_DO:\r
+        entity pain;\r
+        pain = spawn();\r
+        pain.owner = self;\r
+        pain.think = zombie_runattack_damage;\r
+        pain.nextthink = time + cvar("g_monster_zombie_attack_stand_delay");\r
+\r
+        self.attack_finished_single = time + 0.7;\r
+        self.frame = zombie_anim_attackstanding1 + rint(random() * 1);\r
+        dprint("frame:",ftos(self.frame),"\n");\r
+\r
+        return VS_CALL_YES_DOING;\r
+    }\r
+\r
+    return VS_CALL_YES_DONE;\r
+}\r
+\r
+void zombie_think()\r
+{\r
+    self.angles_x *= -1;\r
+    makevectors(self.angles);\r
+    self.angles_x *= -1;\r
+\r
+    if (zombie_scoretarget(self.enemy) == 0)\r
+        self.enemy = world;\r
+\r
+    verbstack_pop(self.verbs_attack);\r
+    //verbstack_pop(self.verbs_move);\r
+\r
+    if not (self.enemy)\r
+        verbstack_pop(self.verbs_idle);\r
+\r
+    zombie_move();\r
+\r
+    if(self.enemy)\r
+        self.nextthink = time;\r
+    else\r
+        self.nextthink = time + 0.2;\r
+}\r
+\r
+void zombie_spawn()\r
+{\r
+    setmodel(self,"models/monsters/zombie.dpm");\r
+\r
+    self.solid          = SOLID_BBOX;\r
+    self.takedamage     = DAMAGE_AIM;\r
+    self.event_damage   = zombie_damage;\r
+    self.enemy          = world;\r
+    self.frame          = zombie_anim_spawn;\r
+    self.think          = zombie_think;\r
+    self.nextthink      = time + 2.1;\r
+    self.pain_finished  = self.nextthink;\r
+    self.movetype       = MOVETYPE_WALK;\r
+    self.health         = cvar("g_monster_zombie_health");\r
+    self.velocity       = '0 0 0';\r
+    self.angles         = self.pos2;\r
+    self.moveto         = self.origin;\r
+    self.flags          = FL_MONSTER;\r
+\r
+    setorigin(self,self.pos1);\r
+    setsize(self,ZOMBIE_MIN,ZOMBIE_MAX);\r
+}\r
+\r
+\r
+void spawnfunc_monster_zombie()\r
+{\r
+    if not(cvar("g_monsters"))\r
+    {\r
+        remove(self);\r
+        return;\r
+    }\r
+\r
+    precache_model("models/monsters/zombie.dpm");\r
+\r
+\r
+    self.verbs_idle   = spawn();\r
+    self.verbs_attack = spawn();\r
+\r
+    self.verbs_idle.owner = self;\r
+    self.verbs_attack.owner = self;\r
+\r
+    self.think      = zombie_spawn;\r
+    self.nextthink  = time + 2;\r
+\r
+    traceline(self.origin + '0 0 10', self.origin - '0 0 32', MOVE_WORLDONLY, self);\r
+\r
+    self.pos1 = trace_endpos;\r
+    self.pos2 = self.angles;\r
+    self.team = MAX_SHOT_DISTANCE -1;\r
+\r
+    verbstack_push(self.verbs_idle, zombie_verb_idle, ZV_IDLE,0 , self);\r
+\r
+    verbstack_push(self.verbs_attack, zombie_verb_attack_findtarget, ZV_ATTACK_FIND,0 , self);\r
+    verbstack_push(self.verbs_attack, zombie_verb_attack_run, ZV_ATTACK_RUN,0 , self);\r
+    verbstack_push(self.verbs_attack, zombie_verb_attack_stand, ZV_ATTACK_STAND,0 , self);\r
+\r
+}\r
+\r
+#endif // MONSTES_ENABLED\r
index 6770476..a2d745f 100644 (file)
@@ -165,5 +165,5 @@ monsters/defs.qc
 monsters/fight.qc
 monsters/ai.qc
 monsters/m_monsters.qc
-
+monsters/monster_zombie.qc
 csqcprojectile.qc