]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/monsters/monster/shambler.qc
0416bbcc4f25fc979a381e9b18f125d0160dd0f1
[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         self.monster_delayedattack = func_null;
36         self.delay = -1;
37         
38         monster_melee(self.enemy, autocvar_g_monster_shambler_damage, 0.3, DEATH_MONSTER_SHAMBLER_SMASH, TRUE);
39 }
40
41 void shambler_delayedsmash()
42 {
43         monsters_setframe(shambler_anim_smash);
44         self.monster_delayedattack = shambler_smash;
45         self.delay = time + 0.7;
46         self.attack_finished_single = time + 1.1;
47 }
48
49 void shambler_swing()
50 {
51         float r = ((random() < 0.5) ? TRUE : FALSE);
52         monsters_setframe((r) ? shambler_anim_swingr : shambler_anim_swingl);
53         monster_melee(self.enemy, autocvar_g_monster_shambler_attack_claw_damage, 0.3, DEATH_MONSTER_SHAMBLER_CLAW, TRUE);
54         self.attack_finished_single = time + 0.8;
55         self.monster_delayedattack = func_null;
56         self.delay = -1;
57         if(r)
58         {
59                 self.monster_delayedattack = shambler_swing;
60                 self.delay = time + 0.5;
61         }
62 }
63
64 void CastLightning()
65 {
66         self.monster_delayedattack = func_null;
67         self.delay = -1;
68
69         local vector org, dir;
70         //vector v = '0 0 0';
71
72         self.effects |= EF_MUZZLEFLASH;
73
74         org = self.origin + '0 0 40';
75
76         dir = self.enemy.origin + '0 0 16' - org;
77         dir = normalize (dir);
78
79         traceline (org, self.origin + dir * 1000, TRUE, self);
80                 
81         FireRailgunBullet (org, org + dir * 1000, autocvar_g_monster_shambler_attack_lightning_damage * monster_skill, 0, 0, 0, 0, 0, DEATH_MONSTER_SHAMBLER_ZAP);
82         
83         // teamcolor / hit beam effect
84         //v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
85         //WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), org, v);
86         
87         te_csqc_lightningarc(org, trace_endpos);
88 }
89
90 float shambler_attack(float attack_type)
91 {
92         switch(attack_type)
93         {
94                 case MONSTER_ATTACK_MELEE:
95                 {
96                         float chance = random();
97
98                         if(chance > 0.6)
99                                 shambler_delayedsmash();
100                         else
101                                 shambler_swing();
102                         
103                         return TRUE;
104                 }
105                 case MONSTER_ATTACK_RANGED:
106                 {
107                         monsters_setframe(shambler_anim_magic);
108                         self.attack_finished_single = time + 1.1;
109                         self.monster_delayedattack = CastLightning;
110                         self.delay = time + 0.6;
111                         
112                         return TRUE;
113                 }
114         }
115         
116         return FALSE;
117 }
118
119 void shambler_die()
120 {
121         Monster_CheckDropCvars ("shambler");
122         
123         self.think = monster_dead_think;
124         self.nextthink = time + self.ticrate;
125         self.ltime = time + 5;
126         monsters_setframe(shambler_anim_death);
127         
128         monster_hook_death(); // for post-death mods
129 }
130
131 void shambler_spawn()
132 {
133         if not(self.health)
134                 self.health = autocvar_g_monster_shambler_health;
135
136         self.damageforcescale   = 0.003;
137         self.classname                  = "monster_shambler";
138         self.monster_attackfunc = shambler_attack;
139         self.nextthink                  = time + random() * 0.5 + 0.1;
140         self.think                              = shambler_think;
141         self.weapon                             = WEP_NEX;
142         
143         monsters_setframe(shambler_anim_stand);
144         
145         monster_setupsounds("shambler");
146         
147         monster_hook_spawn(); // for post-spawn mods
148 }
149
150 void spawnfunc_monster_shambler()
151 {
152         if not(autocvar_g_monster_shambler) { remove(self); return; }
153         
154         self.monster_spawnfunc = spawnfunc_monster_shambler;
155         
156         if(Monster_CheckAppearFlags(self))
157                 return;
158         
159         self.scale = 1.3;
160         
161         if not (monster_initialize(
162                          "Shambler", MONSTER_SHAMBLER,
163                          SHAMBLER_MIN, SHAMBLER_MAX,
164                          FALSE,
165                          shambler_die, shambler_spawn))
166         {
167                 remove(self);
168                 return;
169         }
170 }
171
172 #endif // SVQC