]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/monsters/cl_monsters.qc
Clean up monster armor code
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / monsters / cl_monsters.qc
1 // =========================
2 //  CSQC Monster Properties
3 // =========================
4
5
6 .vector glowmod;
7 void monster_changeteam()
8 {
9         self.glowmod = Team_ColorRGB(self.team - 1);
10         
11         if(self.team)
12         {
13                 self.teamradar_color = Team_ColorRGB(self.team - 1);
14                 self.colormap = 1024 + (self.team - 1) * 17;
15         }
16         else
17         {
18                 self.teamradar_color = '1 0 0';
19                 self.colormap = 1024;
20         }
21 }
22
23 void monster_die()
24 {
25         MON_ACTION(self.monsterid, MR_DEATH);
26         
27         self.solid = SOLID_CORPSE;
28 }
29
30 void monster_draw2d()
31 {
32         if(self.netname == "")
33                 return;
34         
35         if(!autocvar_g_waypointsprite_monsters)
36                 return;
37                 
38         if(autocvar_cl_hidewaypoints)
39                 return;
40                 
41         if(self.health <= 0)
42                 return;
43
44         float dist = vlen(self.origin - view_origin);
45         float t = (GetPlayerColor(player_localnum) + 1);        
46
47         vector o;
48         string txt;
49         
50         if(autocvar_cl_vehicles_hud_tactical)
51         if(dist < 10240 && t != self.team)
52         {
53                 // TODO: Vehicle tactical hud
54                 o = project_3d_to_2d(self.origin + '0 0 1' * ((self.maxs_z + self.mins_z) * 0.5));
55                 if(o_z < 0 
56                 || o_x < (vid_conwidth * waypointsprite_edgeoffset_left) 
57                 || o_y < (vid_conheight * waypointsprite_edgeoffset_top) 
58                 || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))  
59                 || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
60                         return; // Dont draw wp's for monsters out of view
61                 o_z = 0;
62                 if(hud != HUD_NORMAL)
63                 {               
64                         switch(hud)
65                         {
66                                 case HUD_SPIDERBOT:
67                                 case HUD_WAKIZASHI:
68                                 case HUD_RAPTOR:
69                                 case HUD_BUMBLEBEE:  
70                                         vector pz = drawgetimagesize("gfx/vehicles/vth-mover.tga") * 0.25;
71                                         drawpic(o - pz * 0.5, "gfx/vehicles/vth-mover.tga", pz , '1 1 1', 0.75, DRAWFLAG_NORMAL);
72                                         break;
73                         }
74                 }
75         }
76         
77         if(dist > self.maxdistance)
78                 return;
79
80         string spriteimage = self.netname;
81         float a = self.alpha * autocvar_hud_panel_fg_alpha;
82         vector rgb = spritelookupcolor(spriteimage, self.teamradar_color);
83
84         
85         if(self.maxdistance > waypointsprite_normdistance)
86                 a *= pow(bound(0, (self.maxdistance - dist) / (self.maxdistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent);
87         else if(self.maxdistance > 0)
88                 a *= pow(bound(0, (waypointsprite_fadedistance - dist) / (waypointsprite_fadedistance - waypointsprite_normdistance), 1), waypointsprite_distancealphaexponent) * (1 - waypointsprite_minalpha) + waypointsprite_minalpha;
89
90         if(rgb == '0 0 0')
91         {
92                 self.teamradar_color = '1 0 0';
93                 print(sprintf("WARNING: sprite of name %s has no color, using red so you notice it\n", spriteimage)); 
94         }
95
96         txt = self.netname;
97         if(autocvar_g_waypointsprite_spam && waypointsprite_count >= autocvar_g_waypointsprite_spam)
98                 txt = _("Spam");
99         else
100                 txt = spritelookuptext(spriteimage);
101         
102         if(autocvar_g_waypointsprite_uppercase)
103                 txt = strtoupper(txt);
104
105         if(a > 1)
106         {
107                 rgb *= a;
108                 a = 1;
109         }
110
111         if(a <= 0)
112                 return;
113                 
114         rgb = fixrgbexcess(rgb);
115
116         o = project_3d_to_2d(self.origin + '0 0 1' * (self.maxs_z + 15));
117         if(o_z < 0 
118         || o_x < (vid_conwidth * waypointsprite_edgeoffset_left) 
119         || o_y < (vid_conheight * waypointsprite_edgeoffset_top) 
120         || o_x > (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right))  
121         || o_y > (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)))
122                 return; // Dont draw wp's for monsters out of view
123
124         o_z = 0;
125
126         float edgedistance_min, crosshairdistance;
127                 edgedistance_min = min((o_y - (vid_conheight * waypointsprite_edgeoffset_top)), 
128         (o_x - (vid_conwidth * waypointsprite_edgeoffset_left)),
129         (vid_conwidth - (vid_conwidth * waypointsprite_edgeoffset_right)) - o_x, 
130         (vid_conheight - (vid_conheight * waypointsprite_edgeoffset_bottom)) - o_y);
131
132         float vidscale = max(vid_conwidth / vid_width, vid_conheight / vid_height);
133
134         crosshairdistance = sqrt( pow(o_x - vid_conwidth/2, 2) + pow(o_y - vid_conheight/2, 2) );
135
136         t = waypointsprite_scale * vidscale;
137         a *= waypointsprite_alpha;
138
139         {
140                 a = a * (1 - (1 - waypointsprite_distancefadealpha) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
141                 t = t * (1 - (1 - waypointsprite_distancefadescale) * (bound(0, dist/waypointsprite_distancefadedistance, 1)));
142         }
143         if (edgedistance_min < waypointsprite_edgefadedistance) {
144                 a = a * (1 - (1 - waypointsprite_edgefadealpha) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
145                 t = t * (1 - (1 - waypointsprite_edgefadescale) * (1 - bound(0, edgedistance_min/waypointsprite_edgefadedistance, 1)));
146         }
147         if(crosshairdistance < waypointsprite_crosshairfadedistance) {
148                 a = a * (1 - (1 - waypointsprite_crosshairfadealpha) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
149                 t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
150         }
151
152         draw_beginBoldFont();
153         o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);           
154         o = drawspritetext(o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
155         drawhealthbar(
156                         o,
157                         0,
158                         self.health / 255,
159                         '0 0 0',
160                         '0 0 0',
161                         0.5 * SPRITE_HEALTHBAR_WIDTH * t,
162                         0.5 * SPRITE_HEALTHBAR_HEIGHT * t,
163                         SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize,
164                         SPRITE_HEALTHBAR_BORDER * t,
165                         0,
166                         rgb,
167                         a * SPRITE_HEALTHBAR_BORDERALPHA,
168                         rgb,
169                         a * SPRITE_HEALTHBAR_HEALTHALPHA,
170                         DRAWFLAG_NORMAL
171                         );
172         draw_endBoldFont();
173 }
174
175 void monster_draw()
176 {
177         float dt;
178         
179         dt = time - self.move_time;
180         self.move_time = time;
181         if(dt <= 0)
182                 return;
183         
184         fixedmakevectors(self.angles);
185         //movelib_groundalign4point(50, 25, 0.25, 45);
186         setorigin(self, self.origin + self.velocity * dt);
187         self.angles_y = self.move_angles_y;
188 }
189
190 void monster_construct()
191 {
192         entity mon = get_monsterinfo(self.monsterid);
193         
194         if(mon.spawnflags & MONSTER_SIZE_BROKEN)
195                 self.scale = 1.3;
196         
197         self.netname = M_NAME(self.monsterid);
198         
199         setorigin(self, self.origin);
200         setmodel(self, mon.model);
201         setsize(self, mon.mins, mon.maxs);
202         
203         self.move_movetype      = MOVETYPE_BOUNCE;
204         self.health                     = 255;
205         self.solid                      = SOLID_BBOX;
206         self.movetype           = MOVETYPE_BOUNCE;
207         self.move_origin        = self.origin;
208         self.move_time          = time;
209         self.drawmask           = MASK_NORMAL;
210         self.alpha                      = 1;
211         self.gravity            = 1;
212         self.draw                       = monster_draw;
213         self.draw2d                     = monster_draw2d;
214         self.maxdistance        = autocvar_g_waypointsprite_monsters_maxdist;
215 }
216
217 void ent_monster()
218 {
219         float sf;
220         sf = ReadByte();
221         
222         if(sf & MSF_SETUP)
223         {
224                 self.monsterid = ReadByte();
225                 
226                 self.origin_x = ReadCoord();
227                 self.origin_y = ReadCoord();
228                 self.origin_z = ReadCoord();
229                 setorigin(self, self.origin);
230                 
231                 self.angles_x = ReadAngle();
232                 self.angles_y = ReadAngle();
233                 
234                 self.skin = ReadByte();
235                 self.team = ReadByte();
236                 
237                 monster_construct();
238                 monster_changeteam();
239         }
240         
241         if(sf & MSF_ANG)
242         {
243                 self.move_angles_x = ReadShort();
244                 self.move_angles_y = ReadShort();
245                 self.angles = self.move_angles;
246         }
247         
248         if(sf & MSF_MOVE)
249         {
250                 self.origin_x = ReadShort();
251                 self.origin_y = ReadShort();
252                 self.origin_z = ReadShort();
253                 setorigin(self, self.origin);
254                 
255                 self.velocity_x = ReadShort();
256                 self.velocity_y = ReadShort();
257                 self.velocity_z = ReadShort();
258                 
259                 self.move_angles_y = ReadShort();
260                 
261                 self.move_time = time;
262                 self.move_velocity = self.velocity;
263                 self.move_origin = self.origin;
264         }
265         
266         if(sf & MSF_ANIM)
267         {
268                 self.frame1time = ReadCoord();
269                 self.frame = ReadByte();
270         }
271         
272         if(sf & MSF_STATUS)
273         {
274                 self.skin = ReadByte();
275         
276                 float _tmp;
277                 _tmp = ReadByte();
278                 if(_tmp != self.team)
279                 {
280                         self.team = _tmp;
281                         monster_changeteam();
282                 }
283                 
284                 _tmp = ReadByte();
285                 if(_tmp == 4) // respawning
286                         setmodel(self, "null");
287                 
288                 _tmp = ReadByte();
289                 
290                 if(_tmp == 0 && self.health != 0)
291                         monster_die();
292
293                 self.health = _tmp;
294         }
295 }