]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/monsters.qc
e88116a4e18a9cfdb7dcfa3e78d762adc35c2de4
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / monsters.qc
1 string mid2info_model;
2 string mid2info_name;
3 vector mid2info_min;
4 vector mid2info_max;
5
6 float monster_precached[MONSTER_LAST];
7 void monster_mid2info(float _mid);
8
9 void monster_precache(float _mid)
10 {    
11     monster_mid2info(_mid);
12     if(monster_precached[_mid])
13         return;
14
15     switch(_mid)
16     {
17         case MONSTER_ZOMBIE:
18                 {
19                         precache_model(ZOMBIE_MODEL);
20                         break;
21                 }
22                 case MONSTER_OGRE:
23                 {
24                         precache_model(OGRE_MODEL);
25                         break;
26                 }
27                 case MONSTER_ANIMUS:
28                 {
29                         precache_model(ANIMUS_MODEL);
30                         break;
31                 }
32                 case MONSTER_SHAMBLER:
33                 {
34                         precache_model(SHAMBLER_MODEL);
35                         break;
36                 }
37                 case MONSTER_BRUISER:
38                 {
39                         precache_model(BRUISER_MODEL);
40                         break;
41                 }
42                 case MONSTER_MARINE:
43                 {
44                         precache_model(SOLDIER_MODEL);
45                         precache_sound("weapons/shotgun_fire.wav");
46                         precache_sound("weapons/uzi_fire.wav");
47                         precache_sound("weapons/laser_fire.wav");
48                         precache_sound("weapons/reload.wav");
49                         precache_model("models/weapons/v_seeker.md3");
50                         break;
51                 }
52                 case MONSTER_WYVERN:
53                 {
54                         precache_model(WYVERN_MODEL);
55                         break;
56                 }
57                 case MONSTER_CERBERUS:
58                 {
59                         precache_model(CERBERUS_MODEL);
60                         break;
61                 }
62                 case MONSTER_SLIME:
63                 {
64                         precache_model(SLIME_MODEL);
65                         precache_sound("weapons/rocket_impact.wav");
66                         break;
67                 }
68                 case MONSTER_KNIGHT:
69                 {
70                         precache_model(KNIGHT_MODEL);
71                         break;
72                 }
73                 case MONSTER_FISH:
74                 {
75                         precache_model(FISH_MODEL);
76                         break;
77                 }
78                 case MONSTER_MAGE:
79                 {
80                         precache_model(MAGE_MODEL);
81                         break;
82                 }
83                 case MONSTER_SPIDER:
84                 {
85                         precache_model(SPIDER_MODEL);
86
87                         break;
88                 }
89     }    
90     monster_precached[_mid] = TRUE;
91 }
92
93 void Monsters_Precache()
94 {
95         float i;
96         for(i = MONSTER_FIRST + 1; i < MONSTER_LAST; ++i)
97                 monster_precache(i);
98 }
99
100 void monster_mid2info(float _mid)
101 {
102         switch(_mid)
103         {
104                 case MONSTER_ZOMBIE:
105                 {
106                         mid2info_model = ZOMBIE_MODEL;
107                         mid2info_name = "Zombie";
108                         mid2info_min = ZOMBIE_MIN;
109                         mid2info_max = ZOMBIE_MAX;
110                         break;
111                 }
112                 case MONSTER_OGRE:
113                 {
114                         mid2info_model = OGRE_MODEL;
115                         mid2info_name = "Ogre";
116                         mid2info_min = OGRE_MIN;
117                         mid2info_max = OGRE_MAX;
118                         break;
119                 }
120                 case MONSTER_ANIMUS:
121                 {
122                         mid2info_model = ANIMUS_MODEL;
123                         mid2info_name = "Animus";
124                         mid2info_min = ANIMUS_MIN;
125                         mid2info_max = ANIMUS_MAX;
126                         if(self) self.scale = 1.3;
127                         break;
128                 }
129                 case MONSTER_SHAMBLER:
130                 {
131                         mid2info_model = SHAMBLER_MODEL;
132                         mid2info_name = "Shambler";
133                         mid2info_min = SHAMBLER_MIN;
134                         mid2info_max = SHAMBLER_MAX;
135                         if(self) self.scale = 1.3;
136                         break;
137                 }
138                 case MONSTER_BRUISER:
139                 {
140                         mid2info_model = BRUISER_MODEL;
141                         mid2info_name = "Bruiser";
142                         mid2info_min = BRUISER_MIN;
143                         mid2info_max = BRUISER_MAX;
144                         if(self) self.scale = 1.3;
145                         break;
146                 }
147                 case MONSTER_MARINE:
148                 {
149                         mid2info_model = SOLDIER_MODEL;
150                         mid2info_name = "Marine";
151                         mid2info_min = SOLDIER_MIN;
152                         mid2info_max = SOLDIER_MAX;
153                         break;
154                 }
155                 case MONSTER_WYVERN:
156                 {
157                         mid2info_model = WYVERN_MODEL;
158                         mid2info_name = "Wyvern";
159                         mid2info_min = WYVERN_MIN;
160                         mid2info_max = WYVERN_MAX;
161                         if(self) self.scale = 1.3;
162                         break;
163                 }
164                 case MONSTER_CERBERUS:
165                 {
166                         mid2info_model = CERBERUS_MODEL;
167                         mid2info_name = "Cerberus";
168                         mid2info_min = CERBERUS_MIN;
169                         mid2info_max = CERBERUS_MAX;
170                         break;
171                 }
172                 case MONSTER_SLIME:
173                 {
174                         mid2info_model = SLIME_MODEL;
175                         mid2info_name = "Slime";
176                         mid2info_min = SLIME_MIN;
177                         mid2info_max = SLIME_MAX;
178                         break;
179                 }
180                 case MONSTER_KNIGHT:
181                 {
182                         mid2info_model = KNIGHT_MODEL;
183                         mid2info_name = "Knight";
184                         mid2info_min = KNIGHT_MIN;
185                         mid2info_max = KNIGHT_MAX;
186                         if(self) self.scale = 1.3;
187                         break;
188                 }
189                 case MONSTER_FISH:
190                 {
191                         mid2info_model = FISH_MODEL;
192                         mid2info_name = "Rotfish";
193                         mid2info_min = FISH_MIN;
194                         mid2info_max = FISH_MAX;
195                         if(self) self.scale = 1.3;
196                         break;
197                 }
198                 case MONSTER_MAGE:
199                 {
200                         mid2info_model = MAGE_MODEL;
201                         mid2info_name = "Mage";
202                         mid2info_min = MAGE_MIN;
203                         mid2info_max = MAGE_MAX;
204                         break;
205                 }
206                 case MONSTER_SPIDER:
207                 {
208                         mid2info_model = SPIDER_MODEL;
209                         mid2info_name = "Spider";
210                         mid2info_min = SPIDER_MIN;
211                         mid2info_max = SPIDER_MAX;
212                         break;
213                 }
214                 default:
215                 {
216                         dprint("WARNING: Unknown monster in CSQC\n");
217                         break;
218                 }
219         }       
220 }
221
222 .vector glowmod;
223 void monster_changeteam()
224 {       
225         self.glowmod = Team_ColorRGB(self.team - 1);
226         self.teamradar_color = Team_ColorRGB(self.team - 1);
227         
228         if(self.team)
229                 self.colormap = 1024 + (self.team - 1) * 17;
230         else
231                 self.colormap = 1024;
232 }
233
234 void monster_die()
235 {
236         if(self.monsterid == MONSTER_SPIDER)
237                 self.angles += '180 0 0';
238                 
239         self.solid = SOLID_CORPSE;
240 }
241
242 void monster_draw()
243 {        
244     float dt;
245             
246     dt = time - self.move_time;
247     self.move_time = time;
248     if(dt <= 0)
249         return;
250     
251     fixedmakevectors(self.angles);
252     //movelib_groundalign4point(300, 100, 0.25, 45);
253     setorigin(self, self.origin + self.velocity * dt);
254     self.angles_y = self.move_angles_y;  
255 }
256
257 void monster_construct()
258 {       
259         monster_mid2info(self.monsterid);
260         self.netname = mid2info_name;
261
262         setorigin(self, self.origin);
263         setmodel(self, mid2info_model);
264         setsize(self, mid2info_min, mid2info_max);
265         
266         self.move_movetype      = MOVETYPE_BOUNCE;
267         self.health                     = 255;
268         self.solid                      = SOLID_BBOX;
269         self.movetype           = MOVETYPE_BOUNCE; 
270         self.move_origin        = self.origin;
271         self.move_time          = time;
272         self.drawmask           = MASK_NORMAL;  
273         self.alpha                      = 1;
274         self.draw                       = monster_draw;
275 }
276
277 void ent_monster()
278 {
279         float sf;
280         sf = ReadByte();
281
282         if(sf & MSF_SETUP)
283         {
284                 self.monsterid = ReadByte();
285                                 
286                 self.origin_x = ReadCoord();
287                 self.origin_y = ReadCoord();
288                 self.origin_z = ReadCoord();
289                 setorigin(self, self.origin);
290                 
291                 self.angles_x = ReadAngle();
292                 self.angles_y = ReadAngle();
293                 
294                 self.skin = ReadByte();
295                 self.team = ReadByte();
296                 
297                 monster_precache(self.monsterid);
298                 monster_construct();
299                 monster_changeteam();
300         }
301         
302         if(sf & MSF_ANG)
303         {
304                 self.move_angles_x = ReadShort();
305                 self.move_angles_y = ReadShort();
306                 self.angles = self.move_angles;
307         }
308         
309         if(sf & MSF_MOVE)
310         {
311                 self.origin_x = ReadShort();
312                 self.origin_y = ReadShort();
313                 self.origin_z = ReadShort();
314                 setorigin(self, self.origin);
315                 
316                 self.velocity_x = ReadShort();
317                 self.velocity_y = ReadShort();
318                 self.velocity_z = ReadShort();
319                 
320                 self.move_angles_y = ReadShort();
321                         
322                 self.move_time   = time;
323                 self.move_velocity = self.velocity;
324                 self.move_origin   = self.origin;
325         }
326                 
327         if(sf & MSF_ANIM)
328         {
329                 self.frame1time = ReadCoord();
330                 self.frame        = ReadByte();
331         }
332
333         if(sf & MSF_STATUS)
334         {
335                 self.skin = ReadByte();
336         
337                 float _tmp;
338                 _tmp = ReadByte();
339                 if(_tmp != self.team)
340                 {                       
341                         self.team = _tmp;                               
342                         monster_changeteam();
343                 }
344                 
345                 _tmp = ReadByte();
346                 if(_tmp == 4) // respawning
347                         setmodel(self, "null");
348                 
349                 _tmp = ReadByte();
350                 
351                 if(_tmp == 0 && self.health != 0)
352                         monster_die();
353
354                 self.health = _tmp;
355         }
356 }