]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/monsters/monster/wizard.qc
Fix more bad use of .think
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / monsters / monster / wizard.qc
1 // size
2 const vector WIZARD_MIN = '-16 -16 -45';
3 const vector WIZARD_MAX = '16 16 16';
4
5 // model
6 string WIZARD_MODEL = "models/monsters/wizard.mdl";
7
8 #ifdef SVQC
9 // cvars
10 float autocvar_g_monster_wizard;
11 float autocvar_g_monster_wizard_health;
12 float autocvar_g_monster_wizard_speed_walk;
13 float autocvar_g_monster_wizard_speed_run;
14 float autocvar_g_monster_wizard_spike_damage;
15 float autocvar_g_monster_wizard_spike_edgedamage;
16 float autocvar_g_monster_wizard_spike_radius;
17 float autocvar_g_monster_wizard_spike_speed;
18
19 // animations
20 const float wizard_anim_hover   = 0;
21 const float wizard_anim_fly     = 1;
22 const float wizard_anim_magic   = 2;
23 const float wizard_anim_pain    = 3;
24 const float wizard_anim_death   = 4;
25
26 void Wiz_FastExplode()
27 {
28         self.event_damage = func_null;
29         self.takedamage = DAMAGE_NO;
30         RadiusDamage (self, self.realowner, autocvar_g_monster_wizard_spike_damage, autocvar_g_monster_wizard_spike_edgedamage, autocvar_g_monster_wizard_spike_radius, world, 0, self.projectiledeathtype, other);
31
32         remove (self);
33 }
34
35 void Wiz_FastTouch ()
36 {
37         if(other == self.owner)
38                 return;
39                 
40         PROJECTILE_TOUCH;
41                 
42         pointparticles(particleeffectnum("TE_WIZSPIKE"), self.origin, '0 0 0', 1);
43         
44         Wiz_FastExplode();
45 }
46
47 void Wiz_StartFast ()
48 {
49         entity missile;
50         vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
51         
52         self.attack_finished_single = time + 0.2;
53         
54         self.v_angle = self.angles;
55         makevectors (self.angles);
56
57         missile = spawn ();
58         missile.owner = missile.realowner = self;
59         setsize (missile, '0 0 0', '0 0 0');            
60         setorigin (missile, self.origin + v_forward * 14 + '0 0 30' + v_right * 14);
61         missile.enemy = self.enemy;
62         missile.nextthink = time + 3;
63         missile.think = Wiz_FastExplode;
64         missile.velocity = dir * autocvar_g_monster_wizard_spike_speed;
65         missile.avelocity = '300 300 300';
66         missile.solid = SOLID_BBOX;
67         missile.movetype = MOVETYPE_FLYMISSILE;
68         missile.touch = Wiz_FastTouch;
69         missile.projectiledeathtype = DEATH_MONSTER_SCRAG;
70         CSQCProjectile(missile, TRUE, PROJECTILE_CRYLINK, TRUE);
71         
72         missile = spawn ();
73         missile.owner = missile.realowner = self;
74         setsize (missile, '0 0 0', '0 0 0');            
75         setorigin (missile, self.origin + v_forward * 14 + '0 0 30' + v_right * -14);
76         missile.enemy = self.enemy;
77         missile.nextthink = time + 3;
78         missile.touch = Wiz_FastTouch;
79         missile.solid = SOLID_BBOX;
80         missile.movetype = MOVETYPE_FLYMISSILE;
81         missile.think = Wiz_FastExplode;
82         missile.velocity = dir * autocvar_g_monster_wizard_spike_speed;
83         missile.avelocity = '300 300 300';
84         missile.projectiledeathtype = DEATH_MONSTER_SCRAG;
85         CSQCProjectile(missile, TRUE, PROJECTILE_CRYLINK, TRUE);
86 }
87
88 void wizard_think ()
89 {
90         self.think = wizard_think;
91         self.nextthink = time + self.ticrate;
92         
93         monster_move(autocvar_g_monster_wizard_speed_run, autocvar_g_monster_wizard_speed_walk, 300, wizard_anim_fly, wizard_anim_hover, wizard_anim_hover);
94 }
95
96 void wizard_fastattack ()
97 {
98         Wiz_StartFast();
99 }
100
101 void wizard_die ()
102 {
103         Monster_CheckDropCvars ("wizard");
104         
105         self.think                      = monster_dead_think;
106         self.nextthink          = time + self.ticrate;
107         self.ltime                      = time + 5;
108         self.velocity_x         = -200 + 400 * random();
109         self.velocity_y         = -200 + 400 * random();
110         self.velocity_z         = 100 + 100 * random();
111         
112         monsters_setframe(wizard_anim_death);
113         
114         monster_hook_death(); // for post-death mods
115 }
116
117 float Wiz_Missile ()
118 {
119         wizard_fastattack();
120         return TRUE;
121 }
122
123 void wizard_spawn ()
124 {
125         if not(self.health)
126                 self.health = autocvar_g_monster_wizard_health * self.scale;
127         
128         self.classname                  = "monster_wizard";
129         self.checkattack                = GenericCheckAttack;
130         self.attack_ranged              = Wiz_Missile;
131         self.nextthink                  = time + random() * 0.5 + 0.1;
132         self.movetype                   = MOVETYPE_FLY; // TODO: make it fly up/down
133         self.flags                         |= FL_FLY;
134         self.think                              = wizard_think;
135         
136         monster_setupsounds("wizard");
137         
138         monster_hook_spawn(); // for post-spawn mods
139 }
140
141 void spawnfunc_monster_wizard ()
142 {       
143         if not(autocvar_g_monster_wizard) { remove(self); return; }
144         
145         self.monster_spawnfunc = spawnfunc_monster_wizard;
146         
147         if(Monster_CheckAppearFlags(self))
148                 return;
149         
150         self.scale = 1.3;
151         
152         if not (monster_initialize(
153                          "Scrag", MONSTER_SCRAG,
154                          WIZARD_MIN, WIZARD_MAX,
155                          TRUE,
156                          wizard_die, wizard_spawn))
157         {
158                 remove(self);
159                 return;
160         }
161 }
162
163 // compatibility with old spawns
164 void spawnfunc_monster_scrag () { spawnfunc_monster_wizard(); }
165
166 #endif // SVQC