]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/monsters/monster/wyvern.qc
Merge branch 'master' into Mario/monsters
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / monsters / monster / wyvern.qc
1 const vector WYVERN_MIN = '-20 -20 -58';
2 const vector WYVERN_MAX = '20 20 20';
3
4 string WYVERN_MODEL = "models/monsters/wizard.mdl";
5
6 #ifdef SVQC
7 float autocvar_g_monster_wyvern;
8 float autocvar_g_monster_wyvern_health;
9 float autocvar_g_monster_wyvern_speed_walk;
10 float autocvar_g_monster_wyvern_speed_run;
11 float autocvar_g_monster_wyvern_fireball_damage;
12 float autocvar_g_monster_wyvern_fireball_force;
13 float autocvar_g_monster_wyvern_fireball_radius;
14 float autocvar_g_monster_wyvern_fireball_edgedamage;
15 float autocvar_g_monster_wyvern_fireball_damagetime;
16 float autocvar_g_monster_wyvern_fireball_speed;
17
18 const float wyvern_anim_hover   = 0;
19 const float wyvern_anim_fly     = 1;
20 const float wyvern_anim_magic   = 2;
21 const float wyvern_anim_pain    = 3;
22 const float wyvern_anim_death   = 4;
23
24 void wyvern_think()
25 {
26         self.think = wyvern_think;
27         self.nextthink = time + self.ticrate;
28         
29         monster_move(autocvar_g_monster_wyvern_speed_run, autocvar_g_monster_wyvern_speed_walk, 300, wyvern_anim_fly, wyvern_anim_hover, wyvern_anim_hover);
30 }
31
32 void wyvern_fireball_explode()
33 {
34         entity e;
35         if(self)
36         {
37                 pointparticles(particleeffectnum("fireball_explode"), self.origin, '0 0 0', 1);
38                 
39                 RadiusDamage(self, self.realowner, autocvar_g_monster_wyvern_fireball_damage, autocvar_g_monster_wyvern_fireball_edgedamage, autocvar_g_monster_wyvern_fireball_force, world, autocvar_g_monster_wyvern_fireball_radius, self.projectiledeathtype, world);
40                 
41                 for(e = world; (e = findfloat(e, takedamage, DAMAGE_AIM)); ) if(vlen(e.origin - self.origin) <= autocvar_g_monster_wyvern_fireball_radius)
42                         Fire_AddDamage(e, self, 5 * monster_skill, autocvar_g_monster_wyvern_fireball_damagetime, self.projectiledeathtype);
43                 
44                 remove(self);
45         }
46 }
47
48 void wyvern_fireball_touch()
49 {
50         PROJECTILE_TOUCH;
51         
52         wyvern_fireball_explode();
53 }
54
55 void wyvern_fireball()
56 {
57         entity missile = spawn();
58         vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
59         
60         monster_makevectors(self.enemy);
61
62         missile.owner = missile.realowner = self;
63         missile.solid = SOLID_TRIGGER;
64         missile.movetype = MOVETYPE_FLYMISSILE;
65         missile.projectiledeathtype = DEATH_MONSTER_WYVERN;
66         setsize(missile, '-6 -6 -6', '6 6 6');          
67         setorigin(missile, self.origin + self.view_ofs + v_forward * 14);
68         missile.flags = FL_PROJECTILE;
69         missile.velocity = dir * autocvar_g_monster_wyvern_fireball_speed;
70         missile.avelocity = '300 300 300';
71         missile.nextthink = time + 5;
72         missile.think = wyvern_fireball_explode;
73         missile.enemy = self.enemy;
74         missile.touch = wyvern_fireball_touch;
75         CSQCProjectile(missile, TRUE, PROJECTILE_FIREMINE, TRUE);
76 }
77
78 float wyvern_attack(float attack_type)
79 {
80         switch(attack_type)
81         {
82                 case MONSTER_ATTACK_MELEE:
83                 case MONSTER_ATTACK_RANGED:
84                 {
85                         self.attack_finished_single = time + 1.2;
86                         
87                         wyvern_fireball();
88                         
89                         return TRUE;
90                 }
91         }
92         
93         return FALSE;
94 }
95
96 void wyvern_die()
97 {
98         Monster_CheckDropCvars ("wyvern");
99         
100         self.think                      = monster_dead_think;
101         self.nextthink          = time + self.ticrate;
102         self.ltime                      = time + 5;
103         self.velocity_x         = -200 + 400 * random();
104         self.velocity_y         = -200 + 400 * random();
105         self.velocity_z         = 100 + 100 * random();
106         
107         monsters_setframe(wyvern_anim_death);
108         
109         monster_hook_death(); // for post-death mods
110 }
111
112 void wyvern_spawn()
113 {
114         if not(self.health)
115                 self.health = autocvar_g_monster_wyvern_health;
116         
117         self.classname                  = "monster_wyvern";
118         self.monster_attackfunc = wyvern_attack;
119         self.nextthink                  = time + random() * 0.5 + 0.1;
120         self.movetype                   = MOVETYPE_FLY;
121         self.flags                         |= FL_FLY;
122         self.think                              = wyvern_think;
123         
124         monster_setupsounds("wyvern");
125         
126         monster_hook_spawn(); // for post-spawn mods
127 }
128
129 void spawnfunc_monster_wyvern()
130 {
131         if not(autocvar_g_monster_wyvern) { remove(self); return; }
132         
133         self.monster_spawnfunc = spawnfunc_monster_wyvern;
134         
135         if(Monster_CheckAppearFlags(self))
136                 return;
137         
138         self.scale = 1.3;
139         
140         if not (monster_initialize(
141                          "Wyvern", MONSTER_WYVERN,
142                          WYVERN_MIN, WYVERN_MAX,
143                          TRUE,
144                          wyvern_die, wyvern_spawn))
145         {
146                 remove(self);
147                 return;
148         }
149 }
150
151 // compatibility with old spawns
152 void spawnfunc_monster_wizard() { spawnfunc_monster_wyvern(); }
153
154 #endif // SVQC