]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/monsters/monster/cerberus.qc
689f04254cff4760d9abf9dcb7649aab6463b255
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / monsters / monster / cerberus.qc
1 #ifdef REGISTER_MONSTER
2 REGISTER_MONSTER(
3 /* MON_##id   */ CERBERUS,
4 /* function   */ m_cerberus,
5 /* spawnflags */ 0,
6 /* mins,maxs  */ '-16 -16 -24', '16 16 12',
7 /* model      */ "dog.dpm",
8 /* netname    */ "cerberus",
9 /* fullname   */ _("Cerberus")
10 );
11
12 #define CERBERUS_SETTINGS(monster) \
13         MON_ADD_CVAR(monster, health) \
14         MON_ADD_CVAR(monster, attack_bite_damage) \
15         MON_ADD_CVAR(monster, attack_jump_damage) \
16         MON_ADD_CVAR(monster, speed_stop) \
17         MON_ADD_CVAR(monster, speed_run) \
18         MON_ADD_CVAR(monster, speed_walk) 
19
20 #ifdef SVQC
21 CERBERUS_SETTINGS(cerberus)
22 #endif // SVQC
23 #else
24 #ifdef SVQC
25 const float cerberus_anim_idle          = 0;
26 const float cerberus_anim_walk          = 1;
27 const float cerberus_anim_run           = 2;
28 const float cerberus_anim_attack        = 3;
29 const float cerberus_anim_die           = 4;
30 const float cerberus_anim_pain          = 5;
31
32 .float cerberus_last_trace;
33
34 void cerberus_findowner()
35 {
36         if(time < self.cerberus_last_trace || self.monster_owner)
37                 return;
38                 
39         entity head;
40         
41         FOR_EACH_MONSTER(head)
42         if(head.health > 0)
43         if(head.monsterid == MON_BRUISER)
44         if(findentity(world, monster_owner, head) == world)
45         if(vlen(head.origin - self.origin) < self.target_range)
46         if(!IsDifferentTeam(head, self))
47         if(head.enemy == world)
48         {
49                 self.monster_owner = head;
50                 break;
51         }
52                 
53         self.cerberus_last_trace = time + 3;
54 }
55
56 void cerberus_checkowner()
57 {
58         if(time < self.cerberus_last_trace)
59                 return;
60         if(IS_PLAYER(self.monster_owner))
61                 return; // don't check player masters
62
63         if(vlen(self.origin - self.monster_owner.origin) > self.target_range)
64                 self.monster_owner = world;
65         if(self.monster_owner.health < 1)
66                 self.monster_owner = world;
67         if(IsDifferentTeam(self.monster_owner, self))
68                 self.monster_owner = world;
69                 
70         self.cerberus_last_trace = time + 3;
71 }
72
73 void cerberus_touch_jump()
74 {
75         if (other.takedamage)
76         if (vlen(self.velocity) > 300)
77         {
78                 Damage(self.enemy, self, self, MON_CVAR(cerberus, attack_jump_damage) * monster_skill, DEATH_MONSTER_CERBERUS_JUMP, self.enemy.origin, normalize(self.enemy.origin - self.origin));
79                 self.touch = MonsterTouch;
80         }
81
82         if(trace_dphitcontents)
83                 self.touch = MonsterTouch;
84 }
85
86 float cerberus_attack(float attack_type)
87 {
88         switch(attack_type)
89         {
90                 case MONSTER_ATTACK_MELEE:
91                 {
92                         monsters_setframe(cerberus_anim_attack);
93                         self.attack_finished_single = time + 0.7;
94                         monster_melee(self.enemy, MON_CVAR(cerberus, attack_bite_damage), 0.2, DEATH_MONSTER_CERBERUS_BITE, TRUE);
95                         
96                         return TRUE;
97                 }
98                 case MONSTER_ATTACK_RANGED:
99                 {
100                         makevectors(self.angles);
101                         if(monster_leap(cerberus_anim_attack, cerberus_touch_jump, v_forward * 300 + '0 0 200', 0.8))
102                                 return TRUE;
103                 }
104         }
105         
106         return FALSE;
107 }
108
109 void spawnfunc_monster_cerberus()
110 {
111         self.classname = "monster_cerberus";
112         
113         self.monster_spawnfunc = spawnfunc_monster_cerberus;
114         
115         if(Monster_CheckAppearFlags(self))
116                 return;
117         
118         if not(monster_initialize(MON_CERBERUS, FALSE)) { remove(self); return; }
119 }
120
121 // compatibility with old spawns
122 void spawnfunc_monster_dog() { spawnfunc_monster_cerberus(); }
123
124 float m_cerberus(float req)
125 {
126         switch(req)
127         {
128                 case MR_THINK:
129                 {
130                         if(self.monster_owner)
131                                 cerberus_checkowner();
132                         else
133                                 cerberus_findowner();
134                         monster_move(MON_CVAR(cerberus, speed_run), MON_CVAR(cerberus, speed_walk), MON_CVAR(cerberus, speed_stop), cerberus_anim_run, cerberus_anim_walk, cerberus_anim_idle);
135                         return TRUE;
136                 }
137                 case MR_DEATH:
138                 {
139                         if(self.monster_owner.flags & FL_MONSTER)
140                                 self.monster_owner = world;
141                         monsters_setframe(cerberus_anim_die);
142                         return TRUE;
143                 }
144                 case MR_SETUP:
145                 {
146                         if not(self.health) self.health = MON_CVAR(cerberus, health);
147                         
148                         self.monster_loot = spawnfunc_item_health_small;
149                         self.monster_attackfunc = cerberus_attack;
150                         monsters_setframe(cerberus_anim_idle);
151                         
152                         return TRUE;
153                 }
154                 case MR_INIT:
155                 {
156                         // nothing
157                         return TRUE;
158                 }
159                 case MR_CONFIG:
160                 {
161                         MON_CONFIG_SETTINGS(CERBERUS_SETTINGS(cerberus))
162                         return TRUE;
163                 }
164         }
165         
166         return TRUE;
167 }
168
169 #endif // SVQC
170 #ifdef CSQC
171 float m_cerberus(float req)
172 {
173         switch(req)
174         {
175                 case MR_DEATH:
176                 {
177                         // nothing
178                         return TRUE;
179                 }
180                 case MR_INIT:
181                 {
182                         precache_model ("models/monsters/dog.dpm");
183                         return TRUE;
184                 }
185         }
186         
187         return TRUE;
188 }
189
190 #endif // CSQC
191 #endif // REGISTER_MONSTER