]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/monsters/monster/shambler.qc
Merge branch 'master' into Mario/monsters
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / monsters / monster / shambler.qc
1 const vector SHAMBLER_MIN = '-41 -41 -31';
2 const vector SHAMBLER_MAX = '41 41 65';
3
4 string SHAMBLER_MODEL = "models/monsters/shambler.mdl";
5
6 #ifdef SVQC
7 float autocvar_g_monster_shambler;
8 float autocvar_g_monster_shambler_health;
9 float autocvar_g_monster_shambler_damage;
10 float autocvar_g_monster_shambler_attack_lightning_damage;
11 float autocvar_g_monster_shambler_attack_claw_damage;
12 float autocvar_g_monster_shambler_speed_walk;
13 float autocvar_g_monster_shambler_speed_run;
14
15 const float shambler_anim_stand         = 0;
16 const float shambler_anim_walk          = 1;
17 const float shambler_anim_run           = 2;
18 const float shambler_anim_smash         = 3;
19 const float shambler_anim_swingr        = 4;
20 const float shambler_anim_swingl        = 5;
21 const float shambler_anim_magic         = 6;
22 const float shambler_anim_pain          = 7;
23 const float shambler_anim_death         = 8;
24
25 void shambler_think()
26 {
27         self.think = shambler_think;
28         self.nextthink = time + self.ticrate;
29         
30         monster_move(autocvar_g_monster_shambler_speed_run, autocvar_g_monster_shambler_speed_walk, 300, shambler_anim_run, shambler_anim_walk, shambler_anim_stand);
31 }
32
33 void shambler_smash()
34 {
35         monster_melee(self.enemy, autocvar_g_monster_shambler_damage, 0.3, DEATH_MONSTER_SHAMBLER_SMASH, TRUE);
36 }
37
38 void shambler_delayedsmash()
39 {
40         monsters_setframe(shambler_anim_smash);
41         defer(0.7, shambler_smash);
42         self.attack_finished_single = time + 1.1;
43 }
44
45 void shambler_swing()
46 {
47         float r = (random() < 0.5);
48         monsters_setframe((r) ? shambler_anim_swingr : shambler_anim_swingl);
49         monster_melee(self.enemy, autocvar_g_monster_shambler_attack_claw_damage, 0.3, DEATH_MONSTER_SHAMBLER_CLAW, TRUE);
50         self.attack_finished_single = time + 0.8;
51         if(r)
52                 defer(0.5, shambler_swing);
53 }
54
55 void CastLightning()
56 {
57         local vector org, dir;
58         //vector v = '0 0 0';
59
60         self.effects |= EF_MUZZLEFLASH;
61
62         org = self.origin + '0 0 40';
63
64         dir = self.enemy.origin + '0 0 16' - org;
65         dir = normalize (dir);
66
67         traceline (org, self.origin + dir * 1000, TRUE, self);
68                 
69         FireRailgunBullet (org, org + dir * 1000, autocvar_g_monster_shambler_attack_lightning_damage * monster_skill, 0, 0, 0, 0, 0, DEATH_MONSTER_SHAMBLER_ZAP);
70         
71         // teamcolor / hit beam effect
72         //v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
73         //WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), org, v);
74         
75         te_csqc_lightningarc(org, trace_endpos);
76 }
77
78 float shambler_attack(float attack_type)
79 {
80         switch(attack_type)
81         {
82                 case MONSTER_ATTACK_MELEE:
83                 {
84                         float chance = random();
85
86                         if(chance > 0.6)
87                                 shambler_delayedsmash();
88                         else
89                                 shambler_swing();
90                         
91                         return TRUE;
92                 }
93                 case MONSTER_ATTACK_RANGED:
94                 {
95                         monsters_setframe(shambler_anim_magic);
96                         self.attack_finished_single = time + 1.1;
97                         defer(0.6, CastLightning);
98                         
99                         return TRUE;
100                 }
101         }
102         
103         return FALSE;
104 }
105
106 void shambler_die()
107 {
108         Monster_CheckDropCvars ("shambler");
109         
110         self.think = monster_dead_think;
111         self.nextthink = time + self.ticrate;
112         self.ltime = time + 5;
113         monsters_setframe(shambler_anim_death);
114         
115         monster_hook_death(); // for post-death mods
116 }
117
118 void shambler_spawn()
119 {
120         if not(self.health)
121                 self.health = autocvar_g_monster_shambler_health;
122
123         self.damageforcescale   = 0.003;
124         self.classname                  = "monster_shambler";
125         self.monster_attackfunc = shambler_attack;
126         self.nextthink                  = time + random() * 0.5 + 0.1;
127         self.think                              = shambler_think;
128         self.weapon                             = WEP_NEX;
129         
130         monsters_setframe(shambler_anim_stand);
131         
132         monster_setupsounds("shambler");
133         
134         monster_hook_spawn(); // for post-spawn mods
135 }
136
137 void spawnfunc_monster_shambler()
138 {
139         if not(autocvar_g_monster_shambler) { remove(self); return; }
140         
141         self.monster_spawnfunc = spawnfunc_monster_shambler;
142         
143         if(Monster_CheckAppearFlags(self))
144                 return;
145         
146         self.scale = 1.3;
147         
148         if not (monster_initialize(
149                          "Shambler", MONSTER_SHAMBLER,
150                          SHAMBLER_MIN, SHAMBLER_MAX,
151                          FALSE,
152                          shambler_die, shambler_spawn))
153         {
154                 remove(self);
155                 return;
156         }
157 }
158
159 #endif // SVQC