]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/monsters/monster/demon.qc
Merge branch 'master' into mario/monsters
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / monsters / monster / demon.qc
1 // cvars
2 float autocvar_g_monster_demon;
3 float autocvar_g_monster_demon_health;
4 float autocvar_g_monster_demon_attack_jump_damage;
5 float autocvar_g_monster_demon_damage;
6 float autocvar_g_monster_demon_speed_walk;
7 float autocvar_g_monster_demon_speed_run;
8
9 // size
10 const vector DEMON_MIN = '-32 -32 -24';
11 const vector DEMON_MAX = '32 32 24';
12
13 // animation
14 #define demon_anim_stand  0
15 #define demon_anim_walk   1
16 #define demon_anim_run  2
17 #define demon_anim_leap   3
18 #define demon_anim_pain   4
19 #define demon_anim_death  5
20 #define demon_anim_attack 6
21
22 void demon_think ()
23 {
24         self.think = demon_think;
25         self.nextthink = time + 0.1;
26         
27         monster_move(autocvar_g_monster_demon_speed_run, autocvar_g_monster_demon_speed_walk, 100, demon_anim_run, demon_anim_walk, demon_anim_stand);
28 }
29
30 void demon_attack_melee ()
31 {
32         float bigdmg = autocvar_g_monster_demon_damage * self.scale;
33         
34         self.frame = demon_anim_attack;
35         self.attack_finished_single = time + 1;
36         
37         monster_melee(self.enemy, bigdmg * monster_skill, 120, DEATH_MONSTER_FIEND);
38 }
39
40 void Demon_JumpTouch ()
41 {
42         if (self.health <= 0)
43                 return;
44                 
45         float bigdmg = autocvar_g_monster_demon_attack_jump_damage * self.scale;
46
47         if (monster_isvalidtarget(other, self, FALSE))
48         {
49                 if (vlen(self.velocity) > 300)
50                 {
51                         Damage(other, self, self, bigdmg * monster_skill, DEATH_MONSTER_FIEND, other.origin, normalize(other.origin - self.origin));
52                         self.touch = MonsterTouch; // instantly turn it off to stop damage spam
53                 }
54         }
55
56         if(self.flags & FL_ONGROUND)
57                 self.touch = MonsterTouch;
58 }
59
60 float demon_jump ()
61 {
62         makevectors(self.angles);
63         if(monster_leap(demon_anim_leap, Demon_JumpTouch, v_forward * 700 + '0 0 300', 0.8))
64                 return TRUE;
65                 
66         return FALSE;
67 }
68
69 void demon_die ()
70 {
71         Monster_CheckDropCvars ("demon");
72         
73         self.frame                      = demon_anim_death;
74         self.think                      = Monster_Fade; 
75         self.solid                      = SOLID_NOT;
76         self.takedamage         = DAMAGE_NO;
77         self.event_damage   = func_null;
78         self.movetype           = MOVETYPE_TOSS;
79         self.enemy                      = world;
80         self.nextthink          = time + 3;
81         
82         monster_hook_death(); // for post-death mods
83 }
84
85 void demon_spawn ()
86 {
87         if not(self.health)
88                 self.health = autocvar_g_monster_demon_health * self.scale;
89
90         self.damageforcescale   = 0;
91         self.classname                  = "monster_demon";
92         self.checkattack                = GenericCheckAttack;
93         self.attack_melee               = demon_attack_melee;
94         self.attack_ranged              = demon_jump;
95         self.nextthink                  = time + random() * 0.5 + 0.1;
96         self.frame                              = demon_anim_stand;
97         self.think                              = demon_think;
98         self.sprite_height              = 30 * self.scale;
99         
100         monster_hook_spawn(); // for post-spawn mods
101 }
102
103 /* QUAKED monster_demon (1 0 0) (-32 -32 -24) (32 32 64) Ambush */
104 void spawnfunc_monster_demon ()
105 {       
106         if not(autocvar_g_monster_demon) { remove(self); return; }
107         
108         self.monster_spawnfunc = spawnfunc_monster_demon;
109         
110         if(self.spawnflags & MONSTERFLAG_APPEAR)
111         {
112                 self.think = func_null;
113                 self.nextthink = -1;
114                 self.use = Monster_Appear;
115                 return;
116         }
117         
118         self.scale = 1.3;
119         
120         if not (monster_initialize(
121                          "Fiend",
122                          "models/monsters/demon.mdl",
123                          DEMON_MIN, DEMON_MAX,
124                          FALSE,
125                          demon_die, demon_spawn))
126         {
127                 remove(self);
128                 return;
129         }
130 }
131
132 // Compatibility with old spawns
133 void spawnfunc_monster_demon1 () { spawnfunc_monster_demon(); }