Rev 4433 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5 | Plagman | 1 | //------------------------------------------------------------------------- |
2 | /* |
||
1652 | terminx | 3 | Copyright (C) 2010 EDuke32 developers and contributors |
5 | Plagman | 4 | |
1652 | terminx | 5 | This file is part of EDuke32. |
5 | Plagman | 6 | |
7 | EDuke32 is free software; you can redistribute it and/or |
||
8 | modify it under the terms of the GNU General Public License version 2 |
||
9 | as published by the Free Software Foundation. |
||
10 | |||
11 | This program is distributed in the hope that it will be useful, |
||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
14 | |||
15 | See the GNU General Public License for more details. |
||
16 | |||
17 | You should have received a copy of the GNU General Public License |
||
18 | along with this program; if not, write to the Free Software |
||
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||
20 | */ |
||
21 | //------------------------------------------------------------------------- |
||
22 | |||
23 | #include "duke3d.h" |
||
2726 | hendricks2 | 24 | #include "common_game.h" |
149 | terminx | 25 | #include "osd.h" |
1677 | terminx | 26 | #include "player.h" |
1678 | terminx | 27 | #include "demo.h" |
1567 | terminx | 28 | #include "enet/enet.h" |
5 | Plagman | 29 | |
4440 | terminx | 30 | #ifdef __ANDROID__ |
31 | #include "android.h" |
||
32 | #endif |
||
33 | |||
2652 | terminx | 34 | int32_t lastvisinc; |
3408 | helixhorne | 35 | hudweapon_t hudweap; |
36 | |||
2905 | helixhorne | 37 | static int32_t g_snum; |
5 | Plagman | 38 | |
1567 | terminx | 39 | extern int32_t g_levelTextTime, ticrandomseed; |
1068 | terminx | 40 | |
1220 | terminx | 41 | int32_t g_numObituaries = 0; |
42 | int32_t g_numSelfObituaries = 0; |
||
43 | |||
1143 | terminx | 44 | void P_UpdateScreenPal(DukePlayer_t *p) |
5 | Plagman | 45 | { |
1899 | helixhorne | 46 | int32_t intowater = 0; |
2955 | helixhorne | 47 | const int32_t sect = p->cursectnum; |
1899 | helixhorne | 48 | |
1772 | plagman | 49 | if (p->heat_on) p->palette = SLIMEPAL; |
2955 | helixhorne | 50 | else if (sect < 0) p->palette = BASEPAL; |
51 | else if (sector[sect].ceilingpicnum >= FLOORSLIME && sector[sect].ceilingpicnum <= FLOORSLIME+2) |
||
335 | terminx | 52 | { |
1772 | plagman | 53 | p->palette = SLIMEPAL; |
1899 | helixhorne | 54 | intowater = 1; |
335 | terminx | 55 | } |
56 | else |
||
57 | { |
||
3073 | helixhorne | 58 | if (sector[p->cursectnum].lotag == ST_2_UNDERWATER) p->palette = WATERPAL; |
1772 | plagman | 59 | else p->palette = BASEPAL; |
1899 | helixhorne | 60 | intowater = 1; |
5 | Plagman | 61 | } |
2955 | helixhorne | 62 | |
1899 | helixhorne | 63 | g_restorePalette = 1+intowater; |
5 | Plagman | 64 | } |
65 | |||
1143 | terminx | 66 | static void P_IncurDamage(DukePlayer_t *p) |
5 | Plagman | 67 | { |
1611 | terminx | 68 | int32_t damage; |
5 | Plagman | 69 | |
4226 | helixhorne | 70 | if (VM_OnEvent(EVENT_INCURDAMAGE, p->i, P_Get(p->i), -1, 0) != 0) |
3081 | terminx | 71 | return; |
5 | Plagman | 72 | |
3081 | terminx | 73 | sprite[p->i].extra -= p->extra_extra8>>8; |
5 | Plagman | 74 | |
3081 | terminx | 75 | damage = sprite[p->i].extra - p->last_extra; |
5 | Plagman | 76 | |
3081 | terminx | 77 | if (damage >= 0) |
78 | return; |
||
5 | Plagman | 79 | |
3081 | terminx | 80 | p->extra_extra8 = 0; |
5 | Plagman | 81 | |
3081 | terminx | 82 | if (p->inv_amount[GET_SHIELD] > 0) |
83 | { |
||
84 | int32_t shield_damage = damage * (20 + (krand()%30)) / 100; |
||
85 | damage -= shield_damage; |
||
5 | Plagman | 86 | |
3081 | terminx | 87 | p->inv_amount[GET_SHIELD] += shield_damage; |
88 | |||
89 | if (p->inv_amount[GET_SHIELD] < 0) |
||
90 | { |
||
91 | damage += p->inv_amount[GET_SHIELD]; |
||
92 | p->inv_amount[GET_SHIELD] = 0; |
||
5 | Plagman | 93 | } |
94 | } |
||
95 | |||
3081 | terminx | 96 | sprite[p->i].extra = p->last_extra + damage; |
5 | Plagman | 97 | } |
98 | |||
1143 | terminx | 99 | void P_QuickKill(DukePlayer_t *p) |
5 | Plagman | 100 | { |
2643 | helixhorne | 101 | P_PalFrom(p, 48, 48,48,48); |
5 | Plagman | 102 | |
103 | sprite[p->i].extra = 0; |
||
104 | sprite[p->i].cstat |= 32768; |
||
3081 | terminx | 105 | |
1220 | terminx | 106 | if (ud.god == 0) |
107 | A_DoGuts(p->i,JIBS6,8); |
||
5 | Plagman | 108 | } |
109 | |||
1205 | terminx | 110 | static void A_DoWaterTracers(int32_t x1,int32_t y1,int32_t z1,int32_t x2,int32_t y2,int32_t z2,int32_t n) |
5 | Plagman | 111 | { |
1205 | terminx | 112 | int32_t i, xv, yv, zv; |
113 | int16_t sect = -1; |
||
5 | Plagman | 114 | |
115 | i = n+1; |
||
116 | xv = (x2-x1)/i; |
||
117 | yv = (y2-y1)/i; |
||
118 | zv = (z2-z1)/i; |
||
119 | |||
333 | terminx | 120 | if ((klabs(x1-x2)+klabs(y1-y2)) < 3084) |
5 | Plagman | 121 | return; |
122 | |||
1229 | terminx | 123 | for (i=n; i>0; i--) |
5 | Plagman | 124 | { |
125 | x1 += xv; |
||
126 | y1 += yv; |
||
127 | z1 += zv; |
||
128 | updatesector(x1,y1,§); |
||
1490 | terminx | 129 | if (sect < 0) |
130 | break; |
||
131 | |||
3073 | helixhorne | 132 | if (sector[sect].lotag == ST_2_UNDERWATER) |
1490 | terminx | 133 | A_InsertSprite(sect,x1,y1,z1,WATERBUBBLE,-32,4+(krand()&3),4+(krand()&3),krand()&2047,0,0,g_player[0].ps->i,5); |
134 | else |
||
135 | A_InsertSprite(sect,x1,y1,z1,SMALLSMOKE,-32,14,14,0,0,0,g_player[0].ps->i,5); |
||
5 | Plagman | 136 | } |
137 | } |
||
138 | |||
1207 | terminx | 139 | static void A_HitscanProjTrail(const vec3_t *sv, const vec3_t *dv, int32_t ang, int32_t atwith) |
5 | Plagman | 140 | { |
1205 | terminx | 141 | int32_t n, j, i; |
142 | int16_t sect = -1; |
||
1207 | terminx | 143 | vec3_t srcvect; |
144 | vec3_t destvect; |
||
5 | Plagman | 145 | |
3361 | helixhorne | 146 | const projectile_t *const proj = &ProjectileData[atwith]; |
147 | |||
1208 | terminx | 148 | Bmemcpy(&destvect, dv, sizeof(vec3_t)); |
5 | Plagman | 149 | |
3361 | helixhorne | 150 | srcvect.x = sv->x + (sintable[(348+ang+512)&2047]/proj->offset); |
151 | srcvect.y = sv->y + (sintable[(ang+348)&2047]/proj->offset); |
||
152 | srcvect.z = sv->z + 1024+(proj->toffset<<8); |
||
5 | Plagman | 153 | |
1207 | terminx | 154 | n = ((FindDistance2D(srcvect.x-destvect.x,srcvect.y-destvect.y))>>8)+1; |
5 | Plagman | 155 | |
1207 | terminx | 156 | destvect.x = ((destvect.x-srcvect.x)/n); |
157 | destvect.y = ((destvect.y-srcvect.y)/n); |
||
158 | destvect.z = ((destvect.z-srcvect.z)/n); |
||
252 | terminx | 159 | |
1207 | terminx | 160 | srcvect.x += destvect.x>>2; |
161 | srcvect.y += destvect.y>>2; |
||
162 | srcvect.z += (destvect.z>>2); |
||
163 | |||
3361 | helixhorne | 164 | for (i=proj->tnum; i>0; i--) |
5 | Plagman | 165 | { |
1207 | terminx | 166 | srcvect.x += destvect.x; |
167 | srcvect.y += destvect.y; |
||
168 | srcvect.z += destvect.z; |
||
169 | updatesector(srcvect.x,srcvect.y,§); |
||
1488 | terminx | 170 | if (sect < 0) |
171 | break; |
||
1207 | terminx | 172 | getzsofslope(sect,srcvect.x,srcvect.y,&n,&j); |
1488 | terminx | 173 | if (srcvect.z > j || srcvect.z < n) |
861 | terminx | 174 | break; |
3361 | helixhorne | 175 | j = A_InsertSprite(sect,srcvect.x,srcvect.y,srcvect.z,proj->trail,-32, |
176 | proj->txrepeat,proj->tyrepeat,ang,0,0,g_player[0].ps->i,0); |
||
2642 | helixhorne | 177 | changespritestat(j, STAT_ACTOR); |
5 | Plagman | 178 | } |
179 | } |
||
180 | |||
1205 | terminx | 181 | int32_t A_GetHitscanRange(int32_t i) |
5 | Plagman | 182 | { |
1611 | terminx | 183 | int32_t zoff = (PN == APLAYER) ? PHEIGHT : 0; |
2877 | helixhorne | 184 | hitdata_t hit; |
5 | Plagman | 185 | |
1208 | terminx | 186 | SZ -= zoff; |
187 | hitscan((const vec3_t *)&sprite[i],SECT, |
||
5 | Plagman | 188 | sintable[(SA+512)&2047], |
189 | sintable[SA&2047], |
||
2877 | helixhorne | 190 | 0,&hit,CLIPMASK1); |
1611 | terminx | 191 | SZ += zoff; |
5 | Plagman | 192 | |
2877 | helixhorne | 193 | return (FindDistance2D(hit.pos.x-SX,hit.pos.y-SY)); |
5 | Plagman | 194 | } |
195 | |||
3955 | helixhorne | 196 | static int32_t A_FindTargetSprite(const spritetype *s, int32_t aang, int32_t atwith) |
5 | Plagman | 197 | { |
1205 | terminx | 198 | int32_t gotshrinker,gotfreezer; |
199 | int32_t i, j, a, k, cans; |
||
3955 | helixhorne | 200 | static const int32_t aimstats[] = { |
201 | STAT_PLAYER, STAT_DUMMYPLAYER, STAT_ACTOR, STAT_ZOMBIEACTOR |
||
202 | }; |
||
1205 | terminx | 203 | int32_t dx1, dy1, dx2, dy2, dx3, dy3, smax, sdist; |
204 | int32_t xv, yv; |
||
5 | Plagman | 205 | |
4226 | helixhorne | 206 | const int32_t snum = s->picnum == APLAYER ? P_GetP(s) : -1; |
207 | |||
335 | terminx | 208 | if (s->picnum == APLAYER) |
209 | { |
||
4226 | helixhorne | 210 | if (!g_player[snum].ps->auto_aim) |
19 | terminx | 211 | return -1; |
3081 | terminx | 212 | |
4226 | helixhorne | 213 | if (g_player[snum].ps->auto_aim == 2) |
19 | terminx | 214 | { |
4351 | helixhorne | 215 | if (A_CheckSpriteTileFlags(atwith,SFLAG_PROJECTILE) && (ProjectileData[atwith].workslike & PROJECTILE_RPG)) |
19 | terminx | 216 | return -1; |
3955 | helixhorne | 217 | |
218 | switch (DYNAMICTILEMAP(atwith)) |
||
219 | { |
||
220 | case TONGUE__STATIC: |
||
221 | case FREEZEBLAST__STATIC: |
||
222 | case SHRINKSPARK__STATIC: |
||
223 | case SHRINKER__STATIC: |
||
224 | case RPG__STATIC: |
||
225 | case FIRELASER__STATIC: |
||
226 | case SPIT__STATIC: |
||
227 | case COOLEXPLOSION1__STATIC: |
||
228 | return -1; |
||
229 | default: |
||
230 | break; |
||
231 | } |
||
19 | terminx | 232 | } |
233 | } |
||
120 | terminx | 234 | |
235 | a = s->ang; |
||
236 | |||
237 | j = -1; |
||
238 | |||
4226 | helixhorne | 239 | gotshrinker = (s->picnum == APLAYER && PWEAPON(0, g_player[snum].ps->curr_weapon, WorksLike) == SHRINKER_WEAPON); |
240 | gotfreezer = (s->picnum == APLAYER && PWEAPON(0, g_player[snum].ps->curr_weapon, WorksLike) == FREEZE_WEAPON); |
||
5 | Plagman | 241 | |
2984 | helixhorne | 242 | smax = INT32_MAX; |
5 | Plagman | 243 | |
244 | dx1 = sintable[(a+512-aang)&2047]; |
||
245 | dy1 = sintable[(a-aang)&2047]; |
||
246 | dx2 = sintable[(a+512+aang)&2047]; |
||
247 | dy2 = sintable[(a+aang)&2047]; |
||
248 | |||
249 | dx3 = sintable[(a+512)&2047]; |
||
250 | dy3 = sintable[a&2047]; |
||
251 | |||
1229 | terminx | 252 | for (k=0; k<4; k++) |
5 | Plagman | 253 | { |
333 | terminx | 254 | if (j >= 0) |
5 | Plagman | 255 | break; |
1229 | terminx | 256 | for (i=headspritestat[aimstats[k]]; i >= 0; i=nextspritestat[i]) |
333 | terminx | 257 | if (sprite[i].xrepeat > 0 && sprite[i].extra >= 0 && (sprite[i].cstat&(257+32768)) == 257) |
1143 | terminx | 258 | if (A_CheckEnemySprite(&sprite[i]) || k < 2) |
5 | Plagman | 259 | { |
1143 | terminx | 260 | if (A_CheckEnemySprite(&sprite[i]) || PN == APLAYER || PN == SHARK) |
5 | Plagman | 261 | { |
4226 | helixhorne | 262 | if (PN == APLAYER && s->picnum == APLAYER && s != &sprite[i] && |
5 | Plagman | 263 | // ud.ffire == 0 && |
1611 | terminx | 264 | (GTFLAGS(GAMETYPE_PLAYERSFRIENDLY) || (GTFLAGS(GAMETYPE_TDM) && |
4226 | helixhorne | 265 | g_player[P_Get(i)].ps->team == g_player[snum].ps->team))) |
5 | Plagman | 266 | continue; |
267 | |||
333 | terminx | 268 | if (gotshrinker && sprite[i].xrepeat < 30) |
5 | Plagman | 269 | { |
335 | terminx | 270 | if (PN == SHARK) |
271 | { |
||
331 | terminx | 272 | if (sprite[i].xrepeat < 20) continue; |
5 | Plagman | 273 | continue; |
331 | terminx | 274 | } |
398 | terminx | 275 | else if (!(PN >= GREENSLIME && PN <= GREENSLIME+7)) |
5 | Plagman | 276 | continue; |
277 | } |
||
331 | terminx | 278 | if (gotfreezer && sprite[i].pal == 1) continue; |
5 | Plagman | 279 | } |
280 | |||
281 | xv = (SX-s->x); |
||
282 | yv = (SY-s->y); |
||
283 | |||
3081 | terminx | 284 | if ((dy1*xv <= dx1*yv) && (dy2*xv >= dx2*yv)) |
285 | { |
||
286 | sdist = mulscale(dx3,xv,14) + mulscale(dy3,yv,14); |
||
287 | |||
288 | if (sdist > 512 && sdist < smax) |
||
5 | Plagman | 289 | { |
3081 | terminx | 290 | if (s->picnum == APLAYER) |
4226 | helixhorne | 291 | { |
292 | const DukePlayer_t *const ps = g_player[P_GetP(s)].ps; |
||
293 | a = (klabs(scale(SZ-s->z,10,sdist)-(ps->horiz+ps->horizoff-100)) < 100); |
||
294 | } |
||
3081 | terminx | 295 | else a = 1; |
5 | Plagman | 296 | |
3081 | terminx | 297 | if (PN == ORGANTIC || PN == ROTATEGUN) |
298 | cans = cansee(SX,SY,SZ,SECT,s->x,s->y,s->z-(32<<8),s->sectnum); |
||
299 | else cans = cansee(SX,SY,SZ-(32<<8),SECT,s->x,s->y,s->z-(32<<8),s->sectnum); |
||
5 | Plagman | 300 | |
3081 | terminx | 301 | if (a && cans) |
302 | { |
||
303 | smax = sdist; |
||
304 | j = i; |
||
5 | Plagman | 305 | } |
306 | } |
||
3081 | terminx | 307 | } |
5 | Plagman | 308 | } |
309 | } |
||
310 | |||
311 | return j; |
||
312 | } |
||
313 | |||
2979 | helixhorne | 314 | static void A_SetHitData(int32_t i, const hitdata_t *hit) |
315 | { |
||
316 | actor[i].t_data[6] = hit->wall; |
||
317 | actor[i].t_data[7] = hit->sect; |
||
318 | actor[i].t_data[8] = hit->sprite; |
||
319 | } |
||
320 | |||
2980 | helixhorne | 321 | static int32_t CheckShootSwitchTile(int32_t pn) |
322 | { |
||
323 | return pn == DIPSWITCH || pn == DIPSWITCH+1 || |
||
324 | pn == DIPSWITCH2 || pn == DIPSWITCH2+1 || |
||
325 | pn == DIPSWITCH3 || pn == DIPSWITCH3+1 || |
||
326 | pn == HANDSWITCH || pn == HANDSWITCH+1; |
||
327 | } |
||
328 | |||
3462 | helixhorne | 329 | static int32_t safeldist(int32_t spritenum1, const spritetype *s2) |
330 | { |
||
331 | int32_t dst = ldist(&sprite[spritenum1], s2); |
||
332 | return dst ? dst : 1; |
||
333 | } |
||
334 | |||
2983 | helixhorne | 335 | // flags: |
336 | // 1: do sprite center adjustment (cen-=(8<<8)) for GREENSLIME or ROTATEGUN |
||
337 | // 2: do auto getangle only if not RECON (if clear, do unconditionally) |
||
338 | static int32_t GetAutoAimAngle(int32_t i, int32_t p, int32_t atwith, |
||
339 | int32_t cen_add, int32_t flags, |
||
340 | const vec3_t *srcvect, int32_t vel, |
||
341 | int32_t *zvel, int16_t *sa) |
||
5 | Plagman | 342 | { |
3359 | helixhorne | 343 | int32_t j = -1; |
2983 | helixhorne | 344 | |
345 | Bassert((unsigned)p < MAXPLAYERS); |
||
346 | |||
3366 | helixhorne | 347 | #ifdef LUNATIC |
348 | g_player[p].ps->autoaimang = AUTO_AIM_ANGLE; |
||
349 | #else |
||
2983 | helixhorne | 350 | Gv_SetVar(g_iAimAngleVarID, AUTO_AIM_ANGLE, i, p); |
3366 | helixhorne | 351 | #endif |
3081 | terminx | 352 | |
3266 | helixhorne | 353 | if (G_HaveEvent(EVENT_GETAUTOAIMANGLE)) |
2983 | helixhorne | 354 | VM_OnEvent(EVENT_GETAUTOAIMANGLE, i, p, -1, 0); |
355 | |||
356 | { |
||
3366 | helixhorne | 357 | #ifdef LUNATIC |
358 | int32_t aimang = g_player[p].ps->autoaimang; |
||
359 | #else |
||
2983 | helixhorne | 360 | int32_t aimang = Gv_GetVar(g_iAimAngleVarID, i, p); |
3366 | helixhorne | 361 | #endif |
2983 | helixhorne | 362 | if (aimang > 0) |
363 | j = A_FindTargetSprite(&sprite[i], aimang, atwith); |
||
364 | } |
||
365 | |||
366 | if (j >= 0) |
||
367 | { |
||
368 | const spritetype *const spr = &sprite[j]; |
||
369 | int32_t cen = 2*(spr->yrepeat*tilesizy[spr->picnum]) + cen_add; |
||
370 | int32_t dst; |
||
371 | |||
372 | if (flags) |
||
373 | { |
||
374 | int32_t pn = spr->picnum; |
||
375 | if ((pn >= GREENSLIME && pn <= GREENSLIME+7) || spr->picnum==ROTATEGUN) |
||
376 | { |
||
377 | cen -= (8<<8); |
||
378 | } |
||
379 | } |
||
380 | |||
3462 | helixhorne | 381 | dst = safeldist(g_player[p].ps->i, &sprite[j]); |
2983 | helixhorne | 382 | *zvel = ((spr->z - srcvect->z - cen)*vel) / dst; |
383 | |||
384 | if (!(flags&2) || sprite[j].picnum != RECON) |
||
385 | *sa = getangle(spr->x-srcvect->x, spr->y-srcvect->y); |
||
386 | } |
||
387 | |||
388 | return j; |
||
389 | } |
||
390 | |||
3353 | helixhorne | 391 | static void Proj_MaybeSpawn(int32_t k, int32_t atwith, const hitdata_t *hit) |
392 | { |
||
3360 | helixhorne | 393 | // atwith < 0 is for hard-coded projectiles |
394 | int32_t spawntile = atwith < 0 ? -atwith : ProjectileData[atwith].spawns; |
||
395 | |||
396 | if (spawntile >= 0) |
||
3353 | helixhorne | 397 | { |
3360 | helixhorne | 398 | int32_t wh = A_Spawn(k, spawntile); |
3359 | helixhorne | 399 | |
3360 | helixhorne | 400 | if (atwith >= 0) |
401 | { |
||
402 | if (ProjectileData[atwith].sxrepeat > 4) |
||
403 | sprite[wh].xrepeat = ProjectileData[atwith].sxrepeat; |
||
404 | if (ProjectileData[atwith].syrepeat > 4) |
||
405 | sprite[wh].yrepeat = ProjectileData[atwith].syrepeat; |
||
406 | } |
||
3359 | helixhorne | 407 | |
3353 | helixhorne | 408 | A_SetHitData(wh, hit); |
409 | } |
||
410 | } |
||
411 | |||
3360 | helixhorne | 412 | // <extra>: damage that this shotspark does |
3359 | helixhorne | 413 | static int32_t Proj_InsertShotspark(const hitdata_t *hit, int32_t i, int32_t atwith, |
414 | int32_t xyrepeat, int32_t ang, int32_t extra) |
||
3353 | helixhorne | 415 | { |
3359 | helixhorne | 416 | int32_t k = A_InsertSprite(hit->sect, hit->pos.x, hit->pos.y, hit->pos.z, |
417 | SHOTSPARK1,-15, xyrepeat,xyrepeat, ang,0,0,i,4); |
||
418 | sprite[k].extra = extra; |
||
419 | // This is a hack to allow you to detect which weapon spawned a SHOTSPARK1: |
||
420 | sprite[k].yvel = atwith; |
||
3353 | helixhorne | 421 | A_SetHitData(k, hit); |
422 | |||
423 | return k; |
||
424 | } |
||
425 | |||
3359 | helixhorne | 426 | static int32_t Proj_GetExtra(int32_t atwith) |
427 | { |
||
428 | int32_t extra = ProjectileData[atwith].extra; |
||
429 | if (ProjectileData[atwith].extra_rand > 0) |
||
430 | extra += (krand()%ProjectileData[atwith].extra_rand); |
||
431 | return extra; |
||
432 | } |
||
433 | |||
3358 | helixhorne | 434 | static void Proj_MaybeAddSpread(int32_t not_accurate_p, int32_t *zvel, int16_t *sa, |
435 | int32_t zRange, int32_t angRange) |
||
436 | { |
||
437 | if (not_accurate_p) |
||
438 | { |
||
3715 | helixhorne | 439 | // Ranges <= 1 mean no spread at all. A range of 1 calls krand() though. |
440 | if (zRange > 0) |
||
441 | *zvel += zRange/2 - krand()%zRange; |
||
442 | if (angRange > 0) |
||
443 | *sa += angRange/2 - krand()%angRange; |
||
3358 | helixhorne | 444 | } |
445 | } |
||
446 | |||
3465 | helixhorne | 447 | |
3921 | helixhorne | 448 | static int32_t g_overrideShootZvel = 0; // a boolean |
449 | static int32_t g_shootZvel; // the actual zvel if the above is !=0 |
||
3465 | helixhorne | 450 | |
3921 | helixhorne | 451 | static int32_t A_GetShootZvel(int32_t defaultzvel) |
3465 | helixhorne | 452 | { |
3921 | helixhorne | 453 | return g_overrideShootZvel ? g_shootZvel : defaultzvel; |
3465 | helixhorne | 454 | } |
455 | |||
3358 | helixhorne | 456 | // Prepare hitscan weapon fired from player p. |
457 | static void P_PreFireHitscan(int32_t i, int32_t p, int32_t atwith, |
||
458 | vec3_t *srcvect, int32_t *zvel, int16_t *sa, |
||
459 | int32_t accurate_autoaim_p, |
||
460 | int32_t not_accurate_p) |
||
461 | { |
||
462 | int32_t angRange=32; |
||
463 | int32_t zRange=256; |
||
464 | |||
465 | int32_t j = GetAutoAimAngle(i, p, atwith, 5<<8, 0+1, srcvect, 256, zvel, sa); |
||
3366 | helixhorne | 466 | DukePlayer_t *const ps = g_player[p].ps; |
3358 | helixhorne | 467 | |
3366 | helixhorne | 468 | #ifdef LUNATIC |
469 | ps->angrange = angRange; |
||
470 | ps->zrange = zRange; |
||
471 | #else |
||
3358 | helixhorne | 472 | Gv_SetVar(g_iAngRangeVarID,angRange, i,p); |
473 | Gv_SetVar(g_iZRangeVarID,zRange,i,p); |
||
3366 | helixhorne | 474 | #endif |
3358 | helixhorne | 475 | |
476 | if (G_HaveEvent(EVENT_GETSHOTRANGE)) |
||
477 | VM_OnEvent(EVENT_GETSHOTRANGE, i,p, -1, 0); |
||
3366 | helixhorne | 478 | |
3405 | helixhorne | 479 | #ifdef LUNATIC |
3366 | helixhorne | 480 | angRange = ps->angrange; |
481 | zRange = ps->zrange; |
||
482 | #else |
||
3358 | helixhorne | 483 | angRange=Gv_GetVar(g_iAngRangeVarID,i,p); |
484 | zRange=Gv_GetVar(g_iZRangeVarID,i,p); |
||
485 | #endif |
||
3366 | helixhorne | 486 | |
3358 | helixhorne | 487 | if (accurate_autoaim_p) |
488 | { |
||
489 | if (!ps->auto_aim) |
||
490 | { |
||
491 | hitdata_t hit; |
||
492 | |||
3921 | helixhorne | 493 | *zvel = A_GetShootZvel((100-ps->horiz-ps->horizoff)<<5); |
3358 | helixhorne | 494 | |
495 | hitscan(srcvect, sprite[i].sectnum, sintable[(*sa+512)&2047], sintable[*sa&2047], |
||
496 | *zvel<<6,&hit,CLIPMASK1); |
||
497 | |||
498 | if (hit.sprite != -1) |
||
499 | { |
||
500 | const int32_t hitstatnumsbitmap = |
||
501 | ((1<<STAT_ACTOR) | (1<<STAT_ZOMBIEACTOR) | (1<<STAT_PLAYER) | (1<<STAT_DUMMYPLAYER)); |
||
502 | const int32_t st = sprite[hit.sprite].statnum; |
||
503 | |||
504 | if (st>=0 && st<=30 && (hitstatnumsbitmap&(1<<st))) |
||
505 | j = hit.sprite; |
||
506 | } |
||
507 | } |
||
508 | |||
509 | if (j == -1) |
||
510 | { |
||
511 | *zvel = (100-ps->horiz-ps->horizoff)<<5; |
||
512 | Proj_MaybeAddSpread(not_accurate_p, zvel, sa, zRange, angRange); |
||
513 | } |
||
514 | } |
||
515 | else |
||
516 | { |
||
517 | if (j == -1) // no target |
||
518 | *zvel = (100-ps->horiz-ps->horizoff)<<5; |
||
519 | Proj_MaybeAddSpread(not_accurate_p, zvel, sa, zRange, angRange); |
||
520 | } |
||
521 | |||
522 | srcvect->z -= (2<<8); |
||
523 | } |
||
524 | |||
525 | // Hitscan weapon fired from actor (sprite s); |
||
526 | static void A_PreFireHitscan(const spritetype *s, vec3_t *srcvect, int32_t *zvel, int16_t *sa, |
||
527 | int32_t not_accurate_p) |
||
528 | { |
||
3680 | helixhorne | 529 | const int32_t j = A_FindPlayer(s, NULL); |
3358 | helixhorne | 530 | const DukePlayer_t *targetps = g_player[j].ps; |
531 | |||
3680 | helixhorne | 532 | const int32_t d = safeldist(targetps->i, s); |
3358 | helixhorne | 533 | *zvel = ((targetps->pos.z-srcvect->z)<<8) / d; |
534 | |||
535 | srcvect->z -= (4<<8); |
||
536 | |||
537 | if (s->picnum != BOSS1) |
||
538 | { |
||
539 | Proj_MaybeAddSpread(not_accurate_p, zvel, sa, 256, 64); |
||
540 | } |
||
541 | else |
||
542 | { |
||
543 | *sa = getangle(targetps->pos.x-srcvect->x, targetps->pos.y-srcvect->y); |
||
544 | |||
545 | Proj_MaybeAddSpread(not_accurate_p, zvel, sa, 256, 128); |
||
546 | } |
||
547 | } |
||
548 | |||
3360 | helixhorne | 549 | static int32_t Proj_DoHitscan(int32_t i, int32_t cstatmask, |
550 | const vec3_t *srcvect, int32_t zvel, int16_t sa, |
||
551 | hitdata_t *hit) |
||
3359 | helixhorne | 552 | { |
553 | spritetype *const s = &sprite[i]; |
||
554 | |||
555 | s->cstat &= ~cstatmask; |
||
556 | |||
3921 | helixhorne | 557 | zvel = A_GetShootZvel(zvel); |
3359 | helixhorne | 558 | |
559 | hitscan(srcvect, s->sectnum, |
||
560 | sintable[(sa+512)&2047], |
||
561 | sintable[sa&2047], |
||
562 | zvel<<6, hit, CLIPMASK1); |
||
563 | |||
564 | s->cstat |= cstatmask; |
||
565 | |||
566 | return (hit->sect < 0); |
||
567 | } |
||
568 | |||
3362 | helixhorne | 569 | static void Proj_DoRandDecalSize(int32_t spritenum, int32_t atwith) |
570 | { |
||
571 | const projectile_t *const proj = &ProjectileData[atwith]; |
||
572 | |||
573 | if (proj->workslike & PROJECTILE_RANDDECALSIZE) |
||
574 | { |
||
575 | int32_t wh = (krand()&proj->xrepeat); |
||
576 | if (wh < proj->yrepeat) |
||
577 | wh = proj->yrepeat; |
||
578 | sprite[spritenum].xrepeat = wh; |
||
579 | sprite[spritenum].yrepeat = wh; |
||
580 | } |
||
581 | else |
||
582 | { |
||
583 | sprite[spritenum].xrepeat = proj->xrepeat; |
||
584 | sprite[spritenum].yrepeat = proj->yrepeat; |
||
585 | } |
||
586 | } |
||
587 | |||
588 | static int32_t SectorContainsSE13(int32_t sectnum) |
||
589 | { |
||
590 | int32_t i; |
||
591 | if (sectnum >= 0) |
||
592 | for (SPRITES_OF_SECT(sectnum, i)) |
||
593 | if (sprite[i].statnum == STAT_EFFECTOR && sprite[i].lotag == SE_13_EXPLOSIVE) |
||
594 | return 1; |
||
595 | return 0; |
||
596 | } |
||
597 | |||
598 | // Maybe handle bit 2 (swap wall bottoms). |
||
599 | // (in that case walltype *hitwal may be stale) |
||
600 | static void HandleHitWall(hitdata_t *hit) |
||
601 | { |
||
602 | const walltype *const hitwal = &wall[hit->wall]; |
||
603 | |||
604 | if ((hitwal->cstat&2) && redwallp(hitwal)) |
||
605 | if (hit->pos.z >= sector[hitwal->nextsector].floorz) |
||
606 | hit->wall = hitwal->nextwall; |
||
607 | } |
||
608 | |||
4204 | helixhorne | 609 | // Maybe damage a ceiling or floor as the consequence of projectile impact. |
610 | // Returns 1 if projectile hit a parallaxed ceiling. |
||
611 | // NOTE: Compare with Proj_MaybeDamageCF() in actors.c |
||
612 | static int32_t Proj_MaybeDamageCF2(int32_t zvel, int32_t hitsect) |
||
613 | { |
||
614 | if (zvel < 0) |
||
615 | { |
||
616 | Bassert(hitsect >= 0); |
||
617 | |||
618 | if (sector[hitsect].ceilingstat&1) |
||
619 | return 1; |
||
620 | |||
4205 | helixhorne | 621 | Sect_DamageCeilingOrFloor(0, hitsect); |
4204 | helixhorne | 622 | } |
4205 | helixhorne | 623 | else if (zvel > 0) |
624 | { |
||
625 | Bassert(hitsect >= 0); |
||
4204 | helixhorne | 626 | |
4205 | helixhorne | 627 | if (sector[hitsect].floorstat&1) |
628 | { |
||
629 | // Keep original Duke3D behavior: pass projectiles through |
||
630 | // parallaxed ceilings, but NOT through such floors. |
||
631 | return 0; |
||
632 | } |
||
633 | |||
634 | Sect_DamageCeilingOrFloor(1, hitsect); |
||
635 | } |
||
636 | |||
4204 | helixhorne | 637 | return 0; |
638 | } |
||
639 | |||
3360 | helixhorne | 640 | // Finish shooting hitscan weapon from player <p>. <k> is the inserted SHOTSPARK1. |
641 | // * <spawnatimpacttile> is passed to Proj_MaybeSpawn() |
||
642 | // * <decaltile> and <damagewalltile> are for wall impact |
||
643 | // * <damagewalltile> is passed to A_DamageWall() |
||
644 | // * <flags> is for decals upon wall impact: |
||
645 | // 1: handle random decal size (tile <atwith>) |
||
646 | // 2: set cstat to wall-aligned + random x/y flip |
||
647 | // |
||
648 | // TODO: maybe split into 3 cases (hit neither wall nor sprite, hit sprite, hit wall)? |
||
649 | static int32_t P_PostFireHitscan(int32_t p, int32_t k, hitdata_t *hit, int32_t i, int32_t atwith, int32_t zvel, |
||
650 | int32_t spawnatimpacttile, int32_t decaltile, int32_t damagewalltile, |
||
651 | int32_t flags) |
||
652 | { |
||
653 | if (hit->wall == -1 && hit->sprite == -1) |
||
654 | { |
||
4204 | helixhorne | 655 | if (Proj_MaybeDamageCF2(zvel, hit->sect)) |
3360 | helixhorne | 656 | { |
4204 | helixhorne | 657 | sprite[k].xrepeat = 0; |
658 | sprite[k].yrepeat = 0; |
||
659 | return -1; |
||
3360 | helixhorne | 660 | } |
661 | |||
662 | Proj_MaybeSpawn(k, spawnatimpacttile, hit); |
||
663 | } |
||
664 | else if (hit->sprite >= 0) |
||
665 | { |
||
666 | A_DamageObject(hit->sprite, k); |
||
667 | |||
668 | if (sprite[hit->sprite].picnum == APLAYER && |
||
669 | (ud.ffire == 1 || (!GTFLAGS(GAMETYPE_PLAYERSFRIENDLY) && GTFLAGS(GAMETYPE_TDM) && |
||
4226 | helixhorne | 670 | g_player[P_Get(hit->sprite)].ps->team != g_player[P_Get(i)].ps->team))) |
3360 | helixhorne | 671 | { |
672 | int32_t l = A_Spawn(k, JIBS6); |
||
673 | sprite[k].xrepeat = sprite[k].yrepeat = 0; |
||
674 | sprite[l].z += (4<<8); |
||
675 | sprite[l].xvel = 16; |
||
676 | sprite[l].xrepeat = sprite[l].yrepeat = 24; |
||
677 | sprite[l].ang += 64-(krand()&127); |
||
678 | } |
||
679 | else |
||
680 | { |
||
681 | Proj_MaybeSpawn(k, spawnatimpacttile, hit); |
||
682 | } |
||
683 | |||
684 | if (p >= 0 && CheckShootSwitchTile(sprite[hit->sprite].picnum)) |
||
685 | { |
||
686 | P_ActivateSwitch(p, hit->sprite, 1); |
||
687 | return -1; |
||
688 | } |
||
689 | } |
||
690 | else if (hit->wall >= 0) |
||
691 | { |
||
692 | const walltype *const hitwal = &wall[hit->wall]; |
||
693 | |||
694 | Proj_MaybeSpawn(k, spawnatimpacttile, hit); |
||
695 | |||
696 | if (CheckDoorTile(hitwal->picnum) == 1) |
||
697 | goto SKIPBULLETHOLE; |
||
698 | |||
699 | if (p >= 0 && CheckShootSwitchTile(hitwal->picnum)) |
||
700 | { |
||
701 | P_ActivateSwitch(p, hit->wall, 0); |
||
702 | return -1; |
||
703 | } |
||
704 | |||
705 | if (hitwal->hitag != 0 || (hitwal->nextwall >= 0 && wall[hitwal->nextwall].hitag != 0)) |
||
706 | goto SKIPBULLETHOLE; |
||
707 | |||
708 | if (hit->sect >= 0 && sector[hit->sect].lotag == 0) |
||
709 | if (hitwal->overpicnum != BIGFORCE && (hitwal->cstat&16) == 0) |
||
710 | if ((hitwal->nextsector >= 0 && sector[hitwal->nextsector].lotag == 0) || |
||
711 | (hitwal->nextsector == -1 && sector[hit->sect].lotag == 0)) |
||
712 | { |
||
713 | int32_t l; |
||
714 | |||
3362 | helixhorne | 715 | if (SectorContainsSE13(hitwal->nextsector)) |
716 | goto SKIPBULLETHOLE; |
||
3360 | helixhorne | 717 | |
718 | for (SPRITES_OF(STAT_MISC, l)) |
||
719 | if (sprite[l].picnum == decaltile) |
||
720 | if (dist(&sprite[l],&sprite[k]) < (12+(krand()&7))) |
||
721 | goto SKIPBULLETHOLE; |
||
722 | |||
723 | if (decaltile >= 0) |
||
724 | { |
||
725 | l = A_Spawn(k, decaltile); |
||
726 | |||
4351 | helixhorne | 727 | if (!A_CheckSpriteFlags(l, SFLAG_DECAL)) |
728 | actor[l].flags |= SFLAG_DECAL; |
||
3360 | helixhorne | 729 | |
730 | sprite[l].xvel = -1; |
||
731 | sprite[l].ang = getangle(hitwal->x-wall[hitwal->point2].x, |
||
732 | hitwal->y-wall[hitwal->point2].y)+512; |
||
733 | if (flags&1) |
||
3362 | helixhorne | 734 | Proj_DoRandDecalSize(l, atwith); |
3360 | helixhorne | 735 | |
736 | if (flags&2) |
||
737 | sprite[l].cstat = 16+(krand()&(8+4)); |
||
738 | |||
739 | sprite[l].x -= sintable[(sprite[l].ang+2560)&2047]>>13; |
||
740 | sprite[l].y -= sintable[(sprite[l].ang+2048)&2047]>>13; |
||
741 | |||
742 | A_SetSprite(l, CLIPMASK0); |
||
743 | |||
744 | // BULLETHOLE already adds itself to the deletion queue in |
||
745 | // A_Spawn(). However, some other tiles do as well. |
||
746 | if (decaltile != BULLETHOLE) |
||
747 | A_AddToDeleteQueue(l); |
||
748 | } |
||
749 | } |
||
750 | |||
751 | SKIPBULLETHOLE: |
||
3362 | helixhorne | 752 | HandleHitWall(hit); |
3360 | helixhorne | 753 | |
754 | A_DamageWall(k, hit->wall, &hit->pos, damagewalltile); |
||
755 | } |
||
756 | |||
757 | return 0; |
||
758 | } |
||
759 | |||
760 | // Finish shooting hitscan weapon from actor (sprite <i>). |
||
761 | static int32_t A_PostFireHitscan(const hitdata_t *hit, int32_t i, int32_t atwith, int32_t sa, int32_t extra, |
||
762 | int32_t spawnatimpacttile, int32_t damagewalltile) |
||
763 | { |
||
764 | int32_t k = Proj_InsertShotspark(hit, i, atwith, 24, sa, extra); |
||
765 | |||
766 | if (hit->sprite >= 0) |
||
767 | { |
||
768 | A_DamageObject(hit->sprite, k); |
||
769 | |||
770 | if (sprite[hit->sprite].picnum != APLAYER) |
||
771 | Proj_MaybeSpawn(k, spawnatimpacttile, hit); |
||
772 | else |
||
773 | sprite[k].xrepeat = sprite[k].yrepeat = 0; |
||
774 | } |
||
775 | else if (hit->wall >= 0) |
||
776 | A_DamageWall(k, hit->wall, &hit->pos, damagewalltile); |
||
777 | |||
778 | return k; |
||
779 | } |
||
780 | |||
3362 | helixhorne | 781 | // Common "spawn blood?" predicate. |
782 | // minzdiff: minimal "step" height for blood to be spawned |
||
783 | static int32_t Proj_CheckBlood(const vec3_t *srcvect, const hitdata_t *hit, |
||
784 | int32_t projrange, int32_t minzdiff) |
||
785 | { |
||
786 | if (hit->wall >= 0 && hit->sect >= 0) |
||
787 | { |
||
788 | const walltype *const hitwal = &wall[hit->wall]; |
||
789 | |||
790 | if (FindDistance2D(srcvect->x-hit->pos.x, srcvect->y-hit->pos.y) < projrange) |
||
791 | if (hitwal->overpicnum != BIGFORCE && (hitwal->cstat&16) == 0) |
||
792 | if (sector[hit->sect].lotag == 0) |
||
793 | if (hitwal->nextsector < 0 || |
||
794 | (sector[hitwal->nextsector].lotag == 0 && sector[hit->sect].lotag == 0 && |
||
795 | sector[hit->sect].floorz-sector[hitwal->nextsector].floorz > minzdiff)) |
||
796 | return 1; |
||
797 | } |
||
798 | |||
799 | return 0; |
||
800 | } |
||
801 | |||
802 | static void Proj_HandleKnee(hitdata_t *hit, int32_t i, int32_t p, int32_t atwith, int32_t sa, |
||
803 | const projectile_t *proj, int32_t inserttile, |
||
804 | int32_t addrandextra, int32_t spawnatimpacttile, int32_t soundnum) |
||
805 | { |
||
806 | const DukePlayer_t *const ps = p >= 0 ? g_player[p].ps : NULL; |
||
807 | |||
808 | int32_t j = A_InsertSprite(hit->sect,hit->pos.x,hit->pos.y,hit->pos.z, |
||
809 | inserttile,-15,0,0,sa,32,0,i,4); |
||
810 | |||
811 | if (proj != NULL) |
||
812 | { |
||
813 | // Custom projectiles. |
||
814 | SpriteProjectile[j].workslike = ProjectileData[sprite[j].picnum].workslike; |
||
815 | sprite[j].extra = proj->extra; |
||
816 | } |
||
817 | |||
818 | if (addrandextra > 0) |
||
819 | sprite[j].extra += (krand()&addrandextra); |
||
820 | |||
821 | if (p >= 0) |
||
822 | { |
||
823 | if (spawnatimpacttile >= 0) |
||
824 | { |
||
825 | int32_t k = A_Spawn(j, spawnatimpacttile); |
||
826 | sprite[k].z -= (8<<8); |
||
827 | A_SetHitData(k, hit); |
||
828 | } |
||
829 | |||
830 | if (soundnum >= 0) |
||
831 | A_PlaySound(soundnum, j); |
||
832 | } |
||
833 | |||
834 | if (p >= 0 && ps->inv_amount[GET_STEROIDS] > 0 && ps->inv_amount[GET_STEROIDS] < 400) |
||
835 | sprite[j].extra += (ps->max_player_health>>2); |
||
836 | |||
837 | if (hit->sprite >= 0 && sprite[hit->sprite].picnum != ACCESSSWITCH && sprite[hit->sprite].picnum != ACCESSSWITCH2) |
||
838 | { |
||
839 | A_DamageObject(hit->sprite, j); |
||
840 | if (p >= 0) |
||
841 | P_ActivateSwitch(p, hit->sprite,1); |
||
842 | } |
||
843 | else if (hit->wall >= 0) |
||
844 | { |
||
845 | HandleHitWall(hit); |
||
846 | |||
847 | if (wall[hit->wall].picnum != ACCESSSWITCH && wall[hit->wall].picnum != ACCESSSWITCH2) |
||
848 | { |
||
849 | A_DamageWall(j, hit->wall, &hit->pos, atwith); |
||
850 | if (p >= 0) |
||
851 | P_ActivateSwitch(p, hit->wall,0); |
||
852 | } |
||
853 | } |
||
854 | } |
||
855 | |||
3544 | hendricks2 | 856 | #define MinibossScale(s) (((s)*sprite[i].yrepeat)/80) |
3992 | terminx | 857 | |
858 | static int32_t A_ShootCustom(const int32_t i, const int32_t atwith, int16_t sa, vec3_t * const srcvect) |
||
2983 | helixhorne | 859 | { |
3992 | terminx | 860 | /* Custom projectiles */ |
861 | projectile_t *const proj = &ProjectileData[atwith]; |
||
862 | int32_t j, k = -1, l; |
||
3680 | helixhorne | 863 | int32_t vel, zvel = 0; |
2877 | helixhorne | 864 | hitdata_t hit; |
2977 | helixhorne | 865 | spritetype *const s = &sprite[i]; |
866 | const int16_t sect = s->sectnum; |
||
4226 | helixhorne | 867 | const int32_t p = (s->picnum == APLAYER) ? P_GetP(s) : -1; |
2876 | helixhorne | 868 | DukePlayer_t *const ps = p >= 0 ? g_player[p].ps : NULL; |
869 | |||
3992 | terminx | 870 | #ifdef POLYMER |
871 | if (proj->flashcolor) |
||
3465 | helixhorne | 872 | { |
3992 | terminx | 873 | int32_t x = ((sintable[(s->ang + 512) & 2047]) >> 7), y = ((sintable[(s->ang) & 2047]) >> 7); |
874 | |||
875 | s->x += x; |
||
876 | s->y += y; |
||
877 | G_AddGameLight(0, i, PHEIGHT, 8192, proj->flashcolor, PR_LIGHT_PRIO_MAX_GAME); |
||
878 | actor[i].lightcount = 2; |
||
879 | s->x -= x; |
||
880 | s->y -= y; |
||
3465 | helixhorne | 881 | } |
3992 | terminx | 882 | #endif // POLYMER |
3465 | helixhorne | 883 | |
3992 | terminx | 884 | if (proj->offset == 0) |
885 | proj->offset = 1; |
||
5 | Plagman | 886 | |
3992 | terminx | 887 | switch (proj->workslike & PROJECTILE_TYPE_MASK) |
5 | Plagman | 888 | { |
3992 | terminx | 889 | case PROJECTILE_HITSCAN: |
890 | if (s->extra >= 0) s->shade = proj->shade; |
||
1207 | terminx | 891 | |
3992 | terminx | 892 | if (p >= 0) |
893 | P_PreFireHitscan(i, p, atwith, srcvect, &zvel, &sa, |
||
894 | proj->workslike & PROJECTILE_ACCURATE_AUTOAIM, |
||
895 | !(proj->workslike & PROJECTILE_ACCURATE)); |
||
896 | else |
||
897 | A_PreFireHitscan(s, srcvect, &zvel, &sa, |
||
898 | !(proj->workslike & PROJECTILE_ACCURATE)); |
||
3081 | terminx | 899 | |
3992 | terminx | 900 | if (Proj_DoHitscan(i, (proj->cstat >= 0) ? proj->cstat : 256 + 1, |
901 | srcvect, zvel, sa, &hit)) |
||
902 | return -1; |
||
1315 | terminx | 903 | |
3992 | terminx | 904 | if (proj->range > 0 && klabs(srcvect->x - hit.pos.x) + klabs(srcvect->y - hit.pos.y) > proj->range) |
905 | return -1; |
||
1315 | terminx | 906 | |
3992 | terminx | 907 | if (proj->trail >= 0) |
908 | A_HitscanProjTrail(srcvect, &hit.pos, sa, atwith); |
||
5 | Plagman | 909 | |
3992 | terminx | 910 | if (proj->workslike & PROJECTILE_WATERBUBBLES) |
911 | { |
||
912 | if ((krand() & 15) == 0 && sector[hit.sect].lotag == ST_2_UNDERWATER) |
||
913 | A_DoWaterTracers(hit.pos.x, hit.pos.y, hit.pos.z, |
||
914 | srcvect->x, srcvect->y, srcvect->z, 8 - (ud.multimode >> 1)); |
||
915 | } |
||
5 | Plagman | 916 | |
3992 | terminx | 917 | if (p >= 0) |
1319 | terminx | 918 | { |
3992 | terminx | 919 | k = Proj_InsertShotspark(&hit, i, atwith, 10, sa, Proj_GetExtra(atwith)); |
1402 | terminx | 920 | |
3992 | terminx | 921 | if (P_PostFireHitscan(p, k, &hit, i, atwith, zvel, |
922 | atwith, proj->decal, atwith, 1 + 2) < 0) |
||
923 | return -1; |
||
1319 | terminx | 924 | } |
3992 | terminx | 925 | else |
926 | { |
||
927 | k = A_PostFireHitscan(&hit, i, atwith, sa, Proj_GetExtra(atwith), |
||
928 | atwith, atwith); |
||
929 | } |
||
1319 | terminx | 930 | |
3992 | terminx | 931 | if ((krand() & 255) < 4 && proj->isound >= 0) |
932 | S_PlaySound3D(proj->isound, k, &hit.pos); |
||
5 | Plagman | 933 | |
3992 | terminx | 934 | return -1; |
935 | |||
936 | case PROJECTILE_RPG: |
||
937 | if (s->extra >= 0) s->shade = proj->shade; |
||
938 | |||
939 | vel = proj->vel; |
||
940 | |||
941 | j = -1; |
||
942 | |||
943 | if (p >= 0) |
||
5 | Plagman | 944 | { |
4229 | helixhorne | 945 | // NOTE: j is a SPRITE_INDEX |
946 | j = GetAutoAimAngle(i, p, atwith, 8<<8, 0+2, srcvect, vel, &zvel, &sa); |
||
5 | Plagman | 947 | |
3992 | terminx | 948 | if (j < 0) |
4229 | helixhorne | 949 | zvel = (100-ps->horiz-ps->horizoff)*(proj->vel/8); |
5 | Plagman | 950 | |
3992 | terminx | 951 | if (proj->sound >= 0) |
952 | A_PlaySound(proj->sound, i); |
||
953 | } |
||
954 | else |
||
955 | { |
||
956 | if (!(proj->workslike & PROJECTILE_NOAIM)) |
||
5 | Plagman | 957 | { |
4229 | helixhorne | 958 | // NOTE: j is a player index |
3992 | terminx | 959 | j = A_FindPlayer(s, NULL); |
4229 | helixhorne | 960 | sa = getangle(g_player[j].ps->opos.x-srcvect->x, g_player[j].ps->opos.y-srcvect->y); |
3361 | helixhorne | 961 | |
3992 | terminx | 962 | l = safeldist(g_player[j].ps->i, s); |
963 | zvel = ((g_player[j].ps->opos.z - srcvect->z)*vel) / l; |
||
5 | Plagman | 964 | |
4377 | helixhorne | 965 | if (A_CheckEnemySprite(s) && (AC_MOVFLAGS(s, &actor[i]) & face_player_smart)) |
3992 | terminx | 966 | sa = s->ang + (krand() & 31) - 16; |
967 | } |
||
968 | } |
||
5 | Plagman | 969 | |
3992 | terminx | 970 | if (numplayers > 1 && g_netClient) return -1; |
1658 | terminx | 971 | |
4229 | helixhorne | 972 | // l may be a SPRITE_INDEX, see above |
973 | l = (p >= 0 && j >= 0) ? j : -1; |
||
974 | |||
3992 | terminx | 975 | zvel = A_GetShootZvel(zvel); |
976 | j = A_InsertSprite(sect, |
||
977 | srcvect->x + (sintable[(348 + sa + 512) & 2047] / proj->offset), |
||
978 | srcvect->y + (sintable[(sa + 348) & 2047] / proj->offset), |
||
979 | srcvect->z - (1 << 8), atwith, 0, 14, 14, sa, vel, zvel, i, 4); |
||
5 | Plagman | 980 | |
3992 | terminx | 981 | sprite[j].xrepeat = proj->xrepeat; |
982 | sprite[j].yrepeat = proj->yrepeat; |
||
5 | Plagman | 983 | |
3992 | terminx | 984 | if (proj->extra_rand > 0) |
985 | sprite[j].extra += (krand()&proj->extra_rand); |
||
5 | Plagman | 986 | |
3992 | terminx | 987 | if (!(proj->workslike & PROJECTILE_BOUNCESOFFWALLS)) |
4229 | helixhorne | 988 | sprite[j].yvel = l; // NOT_BOUNCESOFFWALLS_YVEL |
3992 | terminx | 989 | else |
990 | { |
||
991 | if (proj->bounces >= 1) sprite[j].yvel = proj->bounces; |
||
992 | else sprite[j].yvel = g_numFreezeBounces; |
||
993 | sprite[j].zvel -= (2 << 4); |
||
994 | } |
||
5 | Plagman | 995 | |
3992 | terminx | 996 | if (proj->cstat >= 0) sprite[j].cstat = proj->cstat; |
997 | else sprite[j].cstat = 128; |
||
5 | Plagman | 998 | |
3992 | terminx | 999 | if (proj->clipdist != 255) sprite[j].clipdist = proj->clipdist; |
1000 | else sprite[j].clipdist = 40; |
||
3361 | helixhorne | 1001 | |
3992 | terminx | 1002 | { |
1003 | int32_t picnum = sprite[j].picnum; // why? |
||
1004 | Bmemcpy(&SpriteProjectile[j], &ProjectileData[picnum], sizeof(projectile_t)); |
||
1005 | } |
||
3362 | helixhorne | 1006 | |
3992 | terminx | 1007 | return j; |
3361 | helixhorne | 1008 | |
3992 | terminx | 1009 | case PROJECTILE_KNEE: |
1010 | if (p >= 0) |
||
1011 | { |
||
1012 | zvel = (100 - ps->horiz - ps->horizoff) << 5; |
||
1013 | srcvect->z += (6 << 8); |
||
1014 | sa += 15; |
||
1015 | } |
||
1016 | else if (!(proj->workslike & PROJECTILE_NOAIM)) |
||
1017 | { |
||
1018 | int32_t x; |
||
1019 | j = g_player[A_FindPlayer(s, &x)].ps->i; |
||
1020 | zvel = ((sprite[j].z - srcvect->z) << 8) / (x + 1); |
||
1021 | sa = getangle(sprite[j].x - srcvect->x, sprite[j].y - srcvect->y); |
||
1022 | } |
||
5 | Plagman | 1023 | |
3992 | terminx | 1024 | Proj_DoHitscan(i, 0, srcvect, zvel, sa, &hit); |
5 | Plagman | 1025 | |
3992 | terminx | 1026 | if (hit.sect < 0) return -1; |
5 | Plagman | 1027 | |
3992 | terminx | 1028 | if (proj->range == 0) |
1029 | proj->range = 1024; |
||
3152 | helixhorne | 1030 | |
3992 | terminx | 1031 | if (proj->range > 0 && klabs(srcvect->x - hit.pos.x) + klabs(srcvect->y - hit.pos.y) > proj->range) |
168 | terminx | 1032 | return -1; |
5 | Plagman | 1033 | |
3992 | terminx | 1034 | Proj_HandleKnee(&hit, i, p, atwith, sa, |
1035 | proj, atwith, |
||
1036 | proj->extra_rand, |
||
1037 | proj->spawns, proj->sound); |
||
5 | Plagman | 1038 | |
3992 | terminx | 1039 | return -1; |
1490 | terminx | 1040 | |
3992 | terminx | 1041 | case PROJECTILE_BLOOD: |
1042 | sa += 64 - (krand() & 127); |
||
1043 | if (p < 0) sa += 1024; |
||
1044 | zvel = 1024 - (krand() & 2047); |
||
1209 | terminx | 1045 | |
3992 | terminx | 1046 | Proj_DoHitscan(i, 0, srcvect, zvel, sa, &hit); |
1209 | terminx | 1047 | |
3992 | terminx | 1048 | if (proj->range == 0) |
1049 | proj->range = 1024; |
||
1209 | terminx | 1050 | |
3992 | terminx | 1051 | if (Proj_CheckBlood(srcvect, &hit, proj->range, |
1052 | mulscale3(proj->yrepeat, tilesizy[proj->decal]) << 8)) |
||
1053 | { |
||
1054 | const walltype *const hitwal = &wall[hit.wall]; |
||
1209 | terminx | 1055 | |
3992 | terminx | 1056 | if (FindDistance2D(hitwal->x - wall[hitwal->point2].x, hitwal->y - wall[hitwal->point2].y) > |
1057 | (mulscale3(proj->xrepeat + 8, tilesizx[proj->decal]))) |
||
1209 | terminx | 1058 | { |
3992 | terminx | 1059 | if (SectorContainsSE13(hitwal->nextsector)) |
1060 | return -1; |
||
1209 | terminx | 1061 | |
3992 | terminx | 1062 | if (hitwal->nextwall >= 0 && wall[hitwal->nextwall].hitag != 0) |
3360 | helixhorne | 1063 | return -1; |
1209 | terminx | 1064 | |
3992 | terminx | 1065 | if (hitwal->hitag == 0 && proj->decal >= 0) |
1066 | { |
||
1067 | k = A_Spawn(i, proj->decal); |
||
1209 | terminx | 1068 | |
4351 | helixhorne | 1069 | if (!A_CheckSpriteFlags(k, SFLAG_DECAL)) |
1070 | actor[k].flags |= SFLAG_DECAL; |
||
1209 | terminx | 1071 | |
3992 | terminx | 1072 | sprite[k].xvel = -1; |
1073 | sprite[k].ang = getangle(hitwal->x - wall[hitwal->point2].x, |
||
1074 | hitwal->y - wall[hitwal->point2].y) + 512; |
||
1075 | Bmemcpy(&sprite[k], &hit.pos, sizeof(vec3_t)); |
||
1209 | terminx | 1076 | |
3992 | terminx | 1077 | Proj_DoRandDecalSize(k, atwith); |
1209 | terminx | 1078 | |
3992 | terminx | 1079 | sprite[k].z += sprite[k].yrepeat << 8; |
1209 | terminx | 1080 | |
3992 | terminx | 1081 | // sprite[k].cstat = 16+(krand()&12); |
1082 | sprite[k].cstat = 16; |
||
1625 | terminx | 1083 | |
3992 | terminx | 1084 | if (krand() & 1) |
1085 | sprite[k].cstat |= 4; |
||
1625 | terminx | 1086 | |
3992 | terminx | 1087 | if (krand() & 1) |
1088 | sprite[k].cstat |= 8; |
||
1209 | terminx | 1089 | |
3992 | terminx | 1090 | sprite[k].shade = sector[sprite[k].sectnum].floorshade; |
1209 | terminx | 1091 | |
3992 | terminx | 1092 | sprite[k].x -= sintable[(sprite[k].ang + 2560) & 2047] >> 13; |
1093 | sprite[k].y -= sintable[(sprite[k].ang + 2048) & 2047] >> 13; |
||
1094 | |||
1095 | A_SetSprite(k, CLIPMASK0); |
||
1096 | A_AddToDeleteQueue(k); |
||
1097 | changespritestat(k, 5); |
||
1209 | terminx | 1098 | } |
1099 | } |
||
3992 | terminx | 1100 | } |
1209 | terminx | 1101 | |
3992 | terminx | 1102 | return -1; |
1209 | terminx | 1103 | |
3992 | terminx | 1104 | default: |
1105 | return -1; |
||
1106 | } |
||
1107 | } |
||
1567 | terminx | 1108 | |
3992 | terminx | 1109 | int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel) |
1110 | { |
||
1111 | int16_t sa; |
||
1112 | vec3_t srcvect; |
||
1113 | spritetype *const s = &sprite[i]; |
||
4226 | helixhorne | 1114 | const int32_t p = (s->picnum == APLAYER) ? P_GetP(s) : -1; |
3992 | terminx | 1115 | DukePlayer_t *const ps = p >= 0 ? g_player[p].ps : NULL; |
1209 | terminx | 1116 | |
3992 | terminx | 1117 | Bassert(atwith >= 0); |
1209 | terminx | 1118 | |
3992 | terminx | 1119 | if (override_zvel != SHOOT_HARDCODED_ZVEL) |
1120 | { |
||
1121 | g_overrideShootZvel = 1; |
||
1122 | g_shootZvel = override_zvel; |
||
1123 | } |
||
1124 | else |
||
1125 | g_overrideShootZvel = 0; |
||
1126 | |||
1127 | if (s->picnum == APLAYER) |
||
1128 | { |
||
1129 | Bmemcpy(&srcvect,ps,sizeof(vec3_t)); |
||
1130 | srcvect.z += ps->pyoff+(4<<8); |
||
1131 | sa = ps->ang; |
||
1132 | |||
1133 | ps->crack_time = 777; |
||
1134 | } |
||
1135 | else |
||
1136 | { |
||
1137 | sa = s->ang; |
||
1138 | Bmemcpy(&srcvect,s,sizeof(vec3_t)); |
||
1139 | srcvect.z -= (((s->yrepeat*tilesizy[s->picnum])<<1)-(4<<8)); |
||
1140 | |||
1141 | if (s->picnum != ROTATEGUN) |
||
1142 | { |
||
1143 | srcvect.z -= (7<<8); |
||
1144 | |||
1145 | if (A_CheckEnemySprite(s) && PN != COMMANDER) |
||
1209 | terminx | 1146 | { |
3992 | terminx | 1147 | srcvect.x += (sintable[(sa+1024+96)&2047]>>7); |
1148 | srcvect.y += (sintable[(sa+512+96)&2047]>>7); |
||
1209 | terminx | 1149 | } |
3992 | terminx | 1150 | } |
3462 | helixhorne | 1151 | |
3992 | terminx | 1152 | #ifdef POLYMER |
1153 | switch (DYNAMICTILEMAP(atwith)) |
||
1154 | { |
||
1155 | case FIRELASER__STATIC: |
||
1156 | case SHOTGUN__STATIC: |
||
1157 | case SHOTSPARK1__STATIC: |
||
1158 | case CHAINGUN__STATIC: |
||
1159 | case RPG__STATIC: |
||
1160 | case MORTER__STATIC: |
||
3152 | helixhorne | 1161 | { |
3992 | terminx | 1162 | int32_t x = ((sintable[(s->ang+512)&2047])>>7), y = ((sintable[(s->ang)&2047])>>7); |
1163 | s->x += x; |
||
1164 | s->y += y; |
||
1165 | G_AddGameLight(0, i, PHEIGHT, 8192, 255+(95<<8), PR_LIGHT_PRIO_MAX_GAME); |
||
1166 | actor[i].lightcount = 2; |
||
1167 | s->x -= x; |
||
1168 | s->y -= y; |
||
3152 | helixhorne | 1169 | } |
1209 | terminx | 1170 | |
3992 | terminx | 1171 | break; |
1209 | terminx | 1172 | } |
3992 | terminx | 1173 | #endif // POLYMER |
1174 | } |
||
1209 | terminx | 1175 | |
4351 | helixhorne | 1176 | if (A_CheckSpriteTileFlags(atwith, SFLAG_PROJECTILE)) |
3992 | terminx | 1177 | return A_ShootCustom(i, atwith, sa, &srcvect); |
1178 | else |
||
1209 | terminx | 1179 | { |
3992 | terminx | 1180 | int32_t j, k = -1, l; |
1181 | int32_t vel, zvel = 0; |
||
1182 | hitdata_t hit; |
||
1183 | const int16_t sect = s->sectnum; |
||
1184 | |||
2297 | helixhorne | 1185 | switch (DYNAMICTILEMAP(atwith)) |
1209 | terminx | 1186 | { |
1187 | case BLOODSPLAT1__STATIC: |
||
1188 | case BLOODSPLAT2__STATIC: |
||
1189 | case BLOODSPLAT3__STATIC: |
||
1190 | case BLOODSPLAT4__STATIC: |
||
1672 | terminx | 1191 | sa += 64 - (krand()&127); |
1192 | if (p < 0) sa += 1024; |
||
1209 | terminx | 1193 | zvel = 1024-(krand()&2047); |
3685 | helixhorne | 1194 | // fall-through |
1209 | terminx | 1195 | case KNEE__STATIC: |
1196 | if (atwith == KNEE) |
||
1197 | { |
||
1198 | if (p >= 0) |
||
1199 | { |
||
2876 | helixhorne | 1200 | zvel = (100-ps->horiz-ps->horizoff)<<5; |
1209 | terminx | 1201 | srcvect.z += (6<<8); |
1202 | sa += 15; |
||
1203 | } |
||
1204 | else |
||
1205 | { |
||
3680 | helixhorne | 1206 | int32_t x; |
1209 | terminx | 1207 | j = g_player[A_FindPlayer(s,&x)].ps->i; |
1208 | zvel = ((sprite[j].z-srcvect.z)<<8) / (x+1); |
||
1209 | sa = getangle(sprite[j].x-srcvect.x,sprite[j].y-srcvect.y); |
||
1210 | } |
||
1211 | } |
||
1212 | |||
3464 | helixhorne | 1213 | Proj_DoHitscan(i, 0, &srcvect, zvel, sa, &hit); |
1209 | terminx | 1214 | |
1220 | terminx | 1215 | if (atwith >= BLOODSPLAT1 && atwith <= BLOODSPLAT4) |
1209 | terminx | 1216 | { |
3362 | helixhorne | 1217 | if (Proj_CheckBlood(&srcvect, &hit, 1024, 16<<8)) |
1209 | terminx | 1218 | { |
3362 | helixhorne | 1219 | const walltype *const hitwal = &wall[hit.wall]; |
1209 | terminx | 1220 | |
3362 | helixhorne | 1221 | if (SectorContainsSE13(hitwal->nextsector)) |
1222 | return -1; |
||
1209 | terminx | 1223 | |
3362 | helixhorne | 1224 | if (hitwal->nextwall >= 0 && wall[hitwal->nextwall].hitag != 0) |
1225 | return -1; |
||
1209 | terminx | 1226 | |
3362 | helixhorne | 1227 | if (hitwal->hitag == 0) |
1209 | terminx | 1228 | { |
3362 | helixhorne | 1229 | k = A_Spawn(i,atwith); |
1230 | sprite[k].xvel = -12; |
||
1231 | sprite[k].ang = getangle(hitwal->x-wall[hitwal->point2].x, |
||
1232 | hitwal->y-wall[hitwal->point2].y)+512; |
||
1233 | Bmemcpy(&sprite[k], &hit.pos, sizeof(vec3_t)); |
||
1209 | terminx | 1234 | |
3362 | helixhorne | 1235 | sprite[k].cstat |= (krand()&4); |
1236 | A_SetSprite(k,CLIPMASK0); |
||
1237 | setsprite(k, (vec3_t *)&sprite[k]); |
||
1238 | if (PN == OOZFILTER || PN == NEWBEAST) |
||
1239 | sprite[k].pal = 6; |
||
1209 | terminx | 1240 | } |
1241 | } |
||
1242 | |||
3362 | helixhorne | 1243 | return -1; |
1209 | terminx | 1244 | } |
3362 | helixhorne | 1245 | |
1246 | if (hit.sect < 0) break; |
||
1247 | |||
1248 | if (klabs(srcvect.x-hit.pos.x)+klabs(srcvect.y-hit.pos.y) < 1024) |
||
1249 | Proj_HandleKnee(&hit, i, p, atwith, sa, |
||
1250 | NULL, KNEE, 7, SMALLSMOKE, KICK_HIT); |
||
1209 | terminx | 1251 | break; |
1252 | |||
1253 | case SHOTSPARK1__STATIC: |
||
1254 | case SHOTGUN__STATIC: |
||
1255 | case CHAINGUN__STATIC: |
||
1256 | if (s->extra >= 0) s->shade = -96; |
||
1257 | |||
1258 | if (p >= 0) |
||
3453 | helixhorne | 1259 | P_PreFireHitscan(i, p, atwith, &srcvect, &zvel, &sa, |
1260 | atwith == SHOTSPARK1__STATIC && !WW2GI && !NAM, |
||
1261 | 1); |
||
1209 | terminx | 1262 | else |
3358 | helixhorne | 1263 | A_PreFireHitscan(s, &srcvect, &zvel, &sa, 1); |
1209 | terminx | 1264 | |
3359 | helixhorne | 1265 | if (Proj_DoHitscan(i, 256+1, &srcvect, zvel, sa, &hit)) |
1266 | return -1; |
||
1209 | terminx | 1267 | |
3073 | helixhorne | 1268 | if ((krand()&15) == 0 && sector[hit.sect].lotag == ST_2_UNDERWATER) |
2877 | helixhorne | 1269 | A_DoWaterTracers(hit.pos.x,hit.pos.y,hit.pos.z, |
1209 | terminx | 1270 | srcvect.x,srcvect.y,srcvect.z,8-(ud.multimode>>1)); |
1271 | |||
1272 | if (p >= 0) |
||
1273 | { |
||
3359 | helixhorne | 1274 | k = Proj_InsertShotspark(&hit, i, atwith, 10, sa, |
1275 | G_InitialActorStrength(atwith) + (krand()%6)); |
||
1209 | terminx | 1276 | |
3360 | helixhorne | 1277 | if (P_PostFireHitscan(p, k, &hit, i, atwith, zvel, |
1278 | -SMALLSMOKE, BULLETHOLE, SHOTSPARK1, 0) < 0) |
||
1279 | return -1; |
||
1209 | terminx | 1280 | } |
1281 | else |
||
1282 | { |
||
3360 | helixhorne | 1283 | k = A_PostFireHitscan(&hit, i, atwith, sa, G_InitialActorStrength(atwith), |
1284 | -SMALLSMOKE, SHOTSPARK1); |
||
1209 | terminx | 1285 | } |
1286 | |||
1287 | if ((krand()&255) < 4) |
||
3360 | helixhorne | 1288 | S_PlaySound3D(PISTOL_RICOCHET, k, &hit.pos); |
1209 | terminx | 1289 | |
1290 | return -1; |
||
1291 | |||
3989 | terminx | 1292 | case GROWSPARK__STATIC: |
1293 | if (p >= 0) |
||
1294 | P_PreFireHitscan(i, p, atwith, &srcvect, &zvel, &sa, 1, 1); |
||
1295 | else |
||
1296 | A_PreFireHitscan(s, &srcvect, &zvel, &sa, 1); |
||
1297 | |||
1298 | if (Proj_DoHitscan(i, 256 + 1, &srcvect, zvel, sa, &hit)) |
||
1299 | return -1; |
||
1300 | |||
1301 | j = A_InsertSprite(hit.sect,hit.pos.x,hit.pos.y,hit.pos.z,GROWSPARK,-16,28,28,sa,0,0,i,1); |
||
1302 | |||
1303 | sprite[j].pal = 2; |
||
1304 | sprite[j].cstat |= 130; |
||
1305 | sprite[j].xrepeat = sprite[j].yrepeat = 1; |
||
1306 | |||
1307 | if (hit.wall == -1 && hit.sprite == -1 && hit.sect >= 0) |
||
1308 | { |
||
4204 | helixhorne | 1309 | Proj_MaybeDamageCF2(zvel, hit.sect); |
3989 | terminx | 1310 | } |
1311 | else if (hit.sprite >= 0) A_DamageObject(hit.sprite,j); |
||
1312 | else if (hit.wall >= 0 && wall[hit.wall].picnum != ACCESSSWITCH && wall[hit.wall].picnum != ACCESSSWITCH2) |
||
1313 | A_DamageWall(j,hit.wall,&hit.pos,atwith); |
||
1314 | |||
1315 | break; |
||
1316 | |||
1209 | terminx | 1317 | case FIRELASER__STATIC: |
1318 | case SPIT__STATIC: |
||
1319 | case COOLEXPLOSION1__STATIC: |
||
3464 | helixhorne | 1320 | { |
1321 | int32_t tsiz; |
||
1209 | terminx | 1322 | |
1323 | if (s->extra >= 0) s->shade = -96; |
||
1324 | |||
3992 | terminx | 1325 | switch (atwith) |
1209 | terminx | 1326 | { |
3992 | terminx | 1327 | case SPIT__STATIC: |
1328 | vel = 292; |
||
1329 | break; |
||
1330 | case COOLEXPLOSION1__STATIC: |
||
1331 | if (s->picnum == BOSS2) vel = 644; |
||
1332 | else vel = 348; |
||
1333 | srcvect.z -= (4<<7); |
||
1334 | break; |
||
1335 | case FIRELASER__STATIC: |
||
1336 | default: |
||
1337 | vel = 840; |
||
1338 | srcvect.z -= (4<<7); |
||
1339 | break; |
||
1209 | terminx | 1340 | } |
1341 | |||
1342 | if (p >= 0) |
||
1343 | { |
||
2983 | helixhorne | 1344 | j = GetAutoAimAngle(i, p, atwith, -(12<<8), 0, &srcvect, vel, &zvel, &sa); |
1209 | terminx | 1345 | |
2983 | helixhorne | 1346 | if (j < 0) |
2876 | helixhorne | 1347 | zvel = (100-ps->horiz-ps->horizoff)*98; |
1209 | terminx | 1348 | } |
1349 | else |
||
1350 | { |
||
3680 | helixhorne | 1351 | j = A_FindPlayer(s, NULL); |
1625 | terminx | 1352 | // sa = getangle(g_player[j].ps->opos.x-sx,g_player[j].ps->opos.y-sy); |
1209 | terminx | 1353 | sa += 16-(krand()&31); |
3462 | helixhorne | 1354 | hit.pos.x = safeldist(g_player[j].ps->i, s); |
2877 | helixhorne | 1355 | zvel = ((g_player[j].ps->opos.z - srcvect.z + (3<<8))*vel) / hit.pos.x; |
1209 | terminx | 1356 | } |
1357 | |||
3921 | helixhorne | 1358 | zvel = A_GetShootZvel(zvel); |
3465 | helixhorne | 1359 | |
1209 | terminx | 1360 | if (atwith == SPIT) |
1361 | { |
||
3464 | helixhorne | 1362 | tsiz = 18; |
1672 | terminx | 1363 | srcvect.z -= (10<<8); |
1209 | terminx | 1364 | } |
1672 | terminx | 1365 | else if (p >= 0) |
3464 | helixhorne | 1366 | tsiz = 7; |
1209 | terminx | 1367 | else |
1368 | { |
||
1369 | if (atwith == FIRELASER) |
||
1370 | { |
||
1371 | if (p >= 0) |
||
3464 | helixhorne | 1372 | tsiz = 34; |
1209 | terminx | 1373 | else |
3464 | helixhorne | 1374 | tsiz = 18; |
1209 | terminx | 1375 | } |
1376 | else |
||
3464 | helixhorne | 1377 | tsiz = 18; |
1209 | terminx | 1378 | } |
1379 | |||
1672 | terminx | 1380 | j = A_InsertSprite(sect,srcvect.x,srcvect.y,srcvect.z, |
3464 | helixhorne | 1381 | atwith,-127,tsiz,tsiz,sa,vel,zvel,i,4); |
1672 | terminx | 1382 | sprite[j].extra += (krand()&7); |
1209 | terminx | 1383 | |
1672 | terminx | 1384 | if (atwith == COOLEXPLOSION1) |
1209 | terminx | 1385 | { |
1672 | terminx | 1386 | sprite[j].shade = 0; |
1387 | if (PN == BOSS2) |
||
1209 | terminx | 1388 | { |
1672 | terminx | 1389 | l = sprite[j].xvel; |
3544 | hendricks2 | 1390 | sprite[j].xvel = MinibossScale(1024); |
1672 | terminx | 1391 | A_SetSprite(j,CLIPMASK0); |
1392 | sprite[j].xvel = l; |
||
1393 | sprite[j].ang += 128-(krand()&255); |
||
1209 | terminx | 1394 | } |
1672 | terminx | 1395 | } |
1209 | terminx | 1396 | |
1672 | terminx | 1397 | sprite[j].cstat = 128; |
1398 | sprite[j].clipdist = 4; |
||
1209 | terminx | 1399 | |
1672 | terminx | 1400 | sa = s->ang+32-(krand()&63); |
3680 | helixhorne | 1401 | zvel += 512-(krand()&1023); |
1209 | terminx | 1402 | |
1403 | return j; |
||
3464 | helixhorne | 1404 | } |
1209 | terminx | 1405 | |
1406 | case FREEZEBLAST__STATIC: |
||
1407 | srcvect.z += (3<<8); |
||
1408 | case RPG__STATIC: |
||
3680 | helixhorne | 1409 | // XXX: "CODEDUP" |
1209 | terminx | 1410 | if (s->extra >= 0) s->shade = -96; |
1411 | |||
1412 | vel = 644; |
||
1413 | |||
1414 | j = -1; |
||
1415 | |||
1416 | if (p >= 0) |
||
1417 | { |
||
4229 | helixhorne | 1418 | // NOTE: j is a SPRITE_INDEX |
2983 | helixhorne | 1419 | j = GetAutoAimAngle(i, p, atwith, 8<<8, 0+2, &srcvect, vel, &zvel, &sa); |
1209 | terminx | 1420 | |
2983 | helixhorne | 1421 | if (j < 0) |
1422 | zvel = (100-ps->horiz-ps->horizoff)*81; |
||
1423 | |||
1209 | terminx | 1424 | if (atwith == RPG) |
1425 | A_PlaySound(RPG_SHOOT,i); |
||
1426 | } |
||
1427 | else |
||
1428 | { |
||
4229 | helixhorne | 1429 | // NOTE: j is a player index |
3680 | helixhorne | 1430 | j = A_FindPlayer(s, NULL); |
4229 | helixhorne | 1431 | sa = getangle(g_player[j].ps->opos.x-srcvect.x, g_player[j].ps->opos.y-srcvect.y); |
1209 | terminx | 1432 | if (PN == BOSS3) |
3544 | hendricks2 | 1433 | srcvect.z -= MinibossScale(32<<8); |
1209 | terminx | 1434 | else if (PN == BOSS2) |
1435 | { |
||
1436 | vel += 128; |
||
3544 | hendricks2 | 1437 | srcvect.z += MinibossScale(24<<8); |
1209 | terminx | 1438 | } |
1439 | |||
3462 | helixhorne | 1440 | l = safeldist(g_player[j].ps->i, s); |
4229 | helixhorne | 1441 | zvel = ((g_player[j].ps->opos.z - srcvect.z)*vel) / l; |
1209 | terminx | 1442 | |
4377 | helixhorne | 1443 | if (A_CheckEnemySprite(s) && (AC_MOVFLAGS(s, &actor[i]) & face_player_smart)) |
1209 | terminx | 1444 | sa = s->ang+(krand()&31)-16; |
1445 | } |
||
1446 | |||
4229 | helixhorne | 1447 | if (numplayers > 1 && g_netClient) |
1448 | return -1; |
||
1567 | terminx | 1449 | |
4229 | helixhorne | 1450 | // l may be a SPRITE_INDEX, see above |
1451 | l = (p >= 0 && j >= 0) ? j : -1; |
||
1567 | terminx | 1452 | |
3921 | helixhorne | 1453 | zvel = A_GetShootZvel(zvel); |
1209 | terminx | 1454 | j = A_InsertSprite(sect, |
1455 | srcvect.x+(sintable[(348+sa+512)&2047]/448), |
||
1456 | srcvect.y+(sintable[(sa+348)&2047]/448), |
||
1457 | srcvect.z-(1<<8),atwith,0,14,14,sa,vel,zvel,i,4); |
||
1458 | |||
1459 | sprite[j].extra += (krand()&7); |
||
1460 | if (atwith != FREEZEBLAST) |
||
4229 | helixhorne | 1461 | sprite[j].yvel = l; // RPG_YVEL |
1209 | terminx | 1462 | else |
1463 | { |
||
1464 | sprite[j].yvel = g_numFreezeBounces; |
||
1465 | sprite[j].xrepeat >>= 1; |
||
1466 | sprite[j].yrepeat >>= 1; |
||
1467 | sprite[j].zvel -= (2<<4); |
||
1468 | } |
||
1469 | |||
1470 | if (p == -1) |
||
1471 | { |
||
1472 | if (PN == BOSS3) |
||
1473 | { |
||
1474 | if (krand()&1) |
||
1475 | { |
||
3544 | hendricks2 | 1476 | sprite[j].x -= MinibossScale(sintable[sa&2047]>>6); |
1477 | sprite[j].y -= MinibossScale(sintable[(sa+1024+512)&2047]>>6); |
||
1478 | sprite[j].ang -= MinibossScale(8); |
||
1209 | terminx | 1479 | } |
1480 | else |
||
1481 | { |
||
3544 | hendricks2 | 1482 | sprite[j].x += MinibossScale(sintable[sa&2047]>>6); |
1483 | sprite[j].y += MinibossScale(sintable[(sa+1024+512)&2047]>>6); |
||
1484 | sprite[j].ang += MinibossScale(4); |
||
1209 | terminx | 1485 | } |
3544 | hendricks2 | 1486 | sprite[j].xrepeat = MinibossScale(42); |
1487 | sprite[j].yrepeat = MinibossScale(42); |
||
1209 | terminx | 1488 | } |
1489 | else if (PN == BOSS2) |
||
1490 | { |
||
3544 | hendricks2 | 1491 | sprite[j].x -= MinibossScale(sintable[sa&2047]/56); |
1492 | sprite[j].y -= MinibossScale(sintable[(sa+1024+512)&2047]/56); |
||
1493 | sprite[j].ang -= MinibossScale(8)+(krand()&255)-128; |
||
1209 | terminx | 1494 | sprite[j].xrepeat = 24; |
1495 | sprite[j].yrepeat = 24; |
||
1496 | } |
||
1497 | else if (atwith != FREEZEBLAST) |
||
1498 | { |
||
1499 | sprite[j].xrepeat = 30; |
||
1500 | sprite[j].yrepeat = 30; |
||
1501 | sprite[j].extra >>= 2; |
||
1502 | } |
||
1503 | } |
||
3328 | helixhorne | 1504 | else if (PWEAPON(0, g_player[p].ps->curr_weapon, WorksLike) == DEVISTATOR_WEAPON) |
1209 | terminx | 1505 | { |
1506 | sprite[j].extra >>= 2; |
||
1507 | sprite[j].ang += 16-(krand()&31); |
||
1508 | sprite[j].zvel += 256-(krand()&511); |
||
1509 | |||
1510 | if (g_player[p].ps->hbomb_hold_delay) |
||
1511 | { |
||
1512 | sprite[j].x -= sintable[sa&2047]/644; |
||
1513 | sprite[j].y -= sintable[(sa+1024+512)&2047]/644; |
||
1514 | } |
||
1515 | else |
||
1516 | { |
||
1517 | sprite[j].x += sintable[sa&2047]>>8; |
||
1518 | sprite[j].y += sintable[(sa+1024+512)&2047]>>8; |
||
1519 | } |
||
1520 | sprite[j].xrepeat >>= 1; |
||
1521 | sprite[j].yrepeat >>= 1; |
||
1522 | } |
||
1523 | |||
1524 | sprite[j].cstat = 128; |
||
1525 | if (atwith == RPG) |
||
1526 | sprite[j].clipdist = 4; |
||
1527 | else |
||
1528 | sprite[j].clipdist = 40; |
||
1529 | |||
1530 | return j; |
||
1531 | |||
1532 | case HANDHOLDINGLASER__STATIC: |
||
2977 | helixhorne | 1533 | { |
1534 | const int32_t zoff = (p>=0) ? g_player[p].ps->pyoff : 0; |
||
1209 | terminx | 1535 | if (p >= 0) |
2876 | helixhorne | 1536 | zvel = (100-ps->horiz-ps->horizoff)*32; |
1209 | terminx | 1537 | else zvel = 0; |
1538 | |||
2977 | helixhorne | 1539 | srcvect.z -= zoff; |
3464 | helixhorne | 1540 | Proj_DoHitscan(i, 0, &srcvect, zvel, sa, &hit); |
2977 | helixhorne | 1541 | srcvect.z += zoff; |
1209 | terminx | 1542 | |
1543 | j = 0; |
||
2877 | helixhorne | 1544 | if (hit.sprite >= 0) break; |
1209 | terminx | 1545 | |
2877 | helixhorne | 1546 | if (hit.wall >= 0 && hit.sect >= 0) |
1547 | if (((hit.pos.x-srcvect.x)*(hit.pos.x-srcvect.x)+(hit.pos.y-srcvect.y)*(hit.pos.y-srcvect.y)) < (290*290)) |
||
1209 | terminx | 1548 | { |
3073 | helixhorne | 1549 | // ST_2_UNDERWATER |
2877 | helixhorne | 1550 | if (wall[hit.wall].nextsector >= 0) |
1209 | terminx | 1551 | { |
2877 | helixhorne | 1552 | if (sector[wall[hit.wall].nextsector].lotag <= 2 && sector[hit.sect].lotag <= 2) |
1209 | terminx | 1553 | j = 1; |
1554 | } |
||
2877 | helixhorne | 1555 | else if (sector[hit.sect].lotag <= 2) |
1209 | terminx | 1556 | j = 1; |
1557 | } |
||
1558 | |||
1559 | if (j == 1) |
||
1560 | { |
||
2977 | helixhorne | 1561 | int32_t lTripBombControl = (p < 0) ? 0 : |
3414 | helixhorne | 1562 | #ifdef LUNATIC |
1563 | g_player[p].ps->tripbombControl; |
||
1564 | #else |
||
2977 | helixhorne | 1565 | Gv_GetVarByLabel("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, g_player[p].ps->i, p); |
3414 | helixhorne | 1566 | #endif |
2877 | helixhorne | 1567 | k = A_InsertSprite(hit.sect,hit.pos.x,hit.pos.y,hit.pos.z,TRIPBOMB,-16,4,5,sa,0,0,i,6); |
1209 | terminx | 1568 | if (lTripBombControl & TRIPBOMB_TIMER) |
1569 | { |
||
3414 | helixhorne | 1570 | #ifdef LUNATIC |
1571 | int32_t lLifetime = g_player[p].ps->tripbombLifetime; |
||
1572 | int32_t lLifetimeVar = g_player[p].ps->tripbombLifetimeVar; |
||
1573 | #else |
||
1209 | terminx | 1574 | int32_t lLifetime=Gv_GetVarByLabel("STICKYBOMB_LIFETIME", NAM_GRENADE_LIFETIME, g_player[p].ps->i, p); |
1575 | int32_t lLifetimeVar=Gv_GetVarByLabel("STICKYBOMB_LIFETIME_VAR", NAM_GRENADE_LIFETIME_VAR, g_player[p].ps->i, p); |
||
3414 | helixhorne | 1576 | #endif |
1209 | terminx | 1577 | // set timer. blows up when at zero.... |
1625 | terminx | 1578 | actor[k].t_data[7]=lLifetime |
1677 | terminx | 1579 | + mulscale(krand(),lLifetimeVar, 14) |
1580 | - lLifetimeVar; |
||
4256 | helixhorne | 1581 | // TIMER_CONTROL |
1625 | terminx | 1582 | actor[k].t_data[6]=1; |
1209 | terminx | 1583 | } |
1584 | else |
||
2977 | helixhorne | 1585 | sprite[k].hitag = k; |
1209 | terminx | 1586 | |
1587 | A_PlaySound(LASERTRIP_ONWALL,k); |
||
1588 | sprite[k].xvel = -20; |
||
1589 | A_SetSprite(k,CLIPMASK0); |
||
1590 | sprite[k].cstat = 16; |
||
1591 | |||
2977 | helixhorne | 1592 | { |
1593 | int32_t p2 = wall[hit.wall].point2; |
||
1594 | int32_t a = getangle(wall[hit.wall].x-wall[p2].x, wall[hit.wall].y-wall[p2].y)-512; |
||
1595 | actor[k].t_data[5] = sprite[k].ang = a; |
||
1596 | } |
||
1209 | terminx | 1597 | } |
1598 | return j?k:-1; |
||
2977 | helixhorne | 1599 | } |
3680 | helixhorne | 1600 | |
1209 | terminx | 1601 | case BOUNCEMINE__STATIC: |
1602 | case MORTER__STATIC: |
||
3680 | helixhorne | 1603 | { |
1604 | int32_t x; |
||
1209 | terminx | 1605 | |
1606 | if (s->extra >= 0) s->shade = -96; |
||
1607 | |||
3680 | helixhorne | 1608 | j = g_player[A_FindPlayer(s, NULL)].ps->i; |
1209 | terminx | 1609 | x = ldist(&sprite[j],s); |
1610 | |||
1611 | zvel = -x>>1; |
||
1612 | |||
1613 | if (zvel < -4096) |
||
1614 | zvel = -2048; |
||
1615 | vel = x>>4; |
||
3465 | helixhorne | 1616 | |
3921 | helixhorne | 1617 | zvel = A_GetShootZvel(zvel); |
1209 | terminx | 1618 | A_InsertSprite(sect, |
1619 | srcvect.x+(sintable[(512+sa+512)&2047]>>8), |
||
1620 | srcvect.y+(sintable[(sa+512)&2047]>>8), |
||
1621 | srcvect.z+(6<<8),atwith,-64,32,32,sa,vel,zvel,i,1); |
||
1622 | break; |
||
3680 | helixhorne | 1623 | } |
1209 | terminx | 1624 | |
1625 | case SHRINKER__STATIC: |
||
1626 | if (s->extra >= 0) s->shade = -96; |
||
1627 | if (p >= 0) |
||
1628 | { |
||
2983 | helixhorne | 1629 | j = GetAutoAimAngle(i, p, atwith, 4<<8, 0, &srcvect, 768, &zvel, &sa); |
1209 | terminx | 1630 | |
2983 | helixhorne | 1631 | if (j < 0) |
1632 | zvel = (100-ps->horiz-ps->horizoff)*98; |
||
1209 | terminx | 1633 | } |
3073 | helixhorne | 1634 | else if (s->statnum != STAT_EFFECTOR) |
1209 | terminx | 1635 | { |
3680 | helixhorne | 1636 | j = A_FindPlayer(s, NULL); |
3462 | helixhorne | 1637 | l = safeldist(g_player[j].ps->i, s); |
1625 | terminx | 1638 | zvel = ((g_player[j].ps->opos.z-srcvect.z)*512) / l ; |
1209 | terminx | 1639 | } |
1640 | else zvel = 0; |
||
3465 | helixhorne | 1641 | |
3921 | helixhorne | 1642 | zvel = A_GetShootZvel(zvel); |
1209 | terminx | 1643 | j = A_InsertSprite(sect, |
1644 | srcvect.x+(sintable[(512+sa+512)&2047]>>12), |
||
1645 | srcvect.y+(sintable[(sa+512)&2047]>>12), |
||
1646 | srcvect.z+(2<<8),SHRINKSPARK,-16,28,28,sa,768,zvel,i,4); |
||
1647 | |||
1648 | sprite[j].cstat = 128; |
||
1649 | sprite[j].clipdist = 32; |
||
1650 | |||
1651 | return j; |
||
1652 | } |
||
1653 | } |
||
3465 | helixhorne | 1654 | |
1209 | terminx | 1655 | return -1; |
1656 | } |
||
1657 | |||
2917 | helixhorne | 1658 | |
1659 | //////////////////// HUD WEAPON / MISC. DISPLAY CODE //////////////////// |
||
1660 | |||
1611 | terminx | 1661 | static void P_DisplaySpit(int32_t snum) |
1209 | terminx | 1662 | { |
1663 | int32_t i, a, x, y, z; |
||
2876 | helixhorne | 1664 | DukePlayer_t *const ps = g_player[snum].ps; |
1209 | terminx | 1665 | |
2876 | helixhorne | 1666 | if (ps->loogcnt == 0) |
2639 | helixhorne | 1667 | return; |
1209 | terminx | 1668 | |
2876 | helixhorne | 1669 | y = (ps->loogcnt<<2); |
2639 | helixhorne | 1670 | |
2876 | helixhorne | 1671 | for (i=0; i<ps->numloogs; i++) |
1209 | terminx | 1672 | { |
2876 | helixhorne | 1673 | a = klabs(sintable[((ps->loogcnt+i)<<5)&2047])>>5; |
1674 | z = 4096+((ps->loogcnt+i)<<9); |
||
1675 | x = (-g_player[snum].sync->avel)+(sintable[((ps->loogcnt+i)<<6)&2047]>>10); |
||
1209 | terminx | 1676 | |
2308 | helixhorne | 1677 | rotatesprite_fs( |
2876 | helixhorne | 1678 | (ps->loogiex[i]+x)<<16,(200+ps->loogiey[i]-y)<<16,z-(i<<8),256-a, |
2308 | helixhorne | 1679 | LOOGIE,0,0,2); |
1209 | terminx | 1680 | } |
1681 | } |
||
1682 | |||
3353 | helixhorne | 1683 | static int32_t P_GetHudPal(const DukePlayer_t *p) |
2518 | helixhorne | 1684 | { |
1685 | if (sprite[p->i].pal == 1) |
||
1686 | return 1; |
||
1687 | |||
1688 | if (p->cursectnum >= 0) |
||
1689 | { |
||
1690 | int32_t dapal = sector[p->cursectnum].floorpal; |
||
1691 | if (!g_noFloorPal[dapal]) |
||
1692 | return dapal; |
||
1693 | } |
||
1694 | |||
1695 | return 0; |
||
1696 | } |
||
1697 | |||
1611 | terminx | 1698 | static int32_t P_DisplayFist(int32_t gs,int32_t snum) |
1209 | terminx | 1699 | { |
1700 | int32_t looking_arc,fisti,fistpal; |
||
1701 | int32_t fistzoom, fistz; |
||
1702 | |||
2932 | helixhorne | 1703 | int32_t wx[2] = { windowx1, windowx2 }; |
1704 | |||
2917 | helixhorne | 1705 | const DukePlayer_t *const ps = g_player[snum].ps; |
1706 | |||
1707 | fisti = ps->fist_incs; |
||
1209 | terminx | 1708 | if (fisti > 32) fisti = 32; |
1709 | if (fisti <= 0) return 0; |
||
1710 | |||
2917 | helixhorne | 1711 | looking_arc = klabs(ps->look_ang)/9; |
1209 | terminx | 1712 | |
2639 | helixhorne | 1713 | fistzoom = 65536 - (sintable[(512+(fisti<<6))&2047]<<2); |
1714 | fistzoom = clamp(fistzoom, 40920, 90612); |
||
1715 | |||
1209 | terminx | 1716 | fistz = 194 + (sintable[((6+fisti)<<7)&2047]>>9); |
1717 | |||
3353 | helixhorne | 1718 | fistpal = P_GetHudPal(ps); |
1209 | terminx | 1719 | |
4249 | hendricks2 | 1720 | #ifdef SPLITSCREEN_MOD_HACKS |
2945 | helixhorne | 1721 | // XXX: this is outdated, doesn't handle above/below split. |
2957 | helixhorne | 1722 | if (g_fakeMultiMode==2) |
2932 | helixhorne | 1723 | wx[(g_snum==0)] = (wx[0]+wx[1])/2+1; |
4249 | hendricks2 | 1724 | #endif |
2932 | helixhorne | 1725 | |
1726 | rotatesprite( |
||
1209 | terminx | 1727 | (-fisti+222+(g_player[snum].sync->avel>>4))<<16, |
1728 | (looking_arc+fistz)<<16, |
||
2932 | helixhorne | 1729 | fistzoom,0,FIST,gs,fistpal,2, |
1730 | wx[0],windowy1,wx[1],windowy2); |
||
1209 | terminx | 1731 | |
1732 | return 1; |
||
1733 | } |
||
1734 | |||
2917 | helixhorne | 1735 | #define DRAWEAP_CENTER 262144 |
3992 | terminx | 1736 | #define weapsc(sc) scale(sc, ud.weaponscale, 100) |
2917 | helixhorne | 1737 | |
3695 | helixhorne | 1738 | static int32_t g_dts_yadd; |
1739 | |||
1209 | terminx | 1740 | static void G_DrawTileScaled(int32_t x, int32_t y, int32_t tilenum, int32_t shade, int32_t orientation, int32_t p) |
1741 | { |
||
2931 | helixhorne | 1742 | int32_t ang = 0; |
1209 | terminx | 1743 | int32_t xoff = 192; |
1744 | |||
2931 | helixhorne | 1745 | int32_t wx[2] = { windowx1, windowx2 }; |
2944 | helixhorne | 1746 | int32_t wy[2] = { windowy1, windowy2 }; |
1747 | int32_t yofs = 0; |
||
2905 | helixhorne | 1748 | |
3408 | helixhorne | 1749 | switch (hudweap.cur) |
1209 | terminx | 1750 | { |
1751 | case DEVISTATOR_WEAPON: |
||
1752 | case TRIPBOMB_WEAPON: |
||
1753 | xoff = 160; |
||
1754 | break; |
||
1755 | default: |
||
2917 | helixhorne | 1756 | if (orientation & DRAWEAP_CENTER) |
1209 | terminx | 1757 | { |
1758 | xoff = 160; |
||
2917 | helixhorne | 1759 | orientation &= ~DRAWEAP_CENTER; |
1209 | terminx | 1760 | } |
1761 | break; |
||
1762 | } |
||
1763 | |||
3353 | helixhorne | 1764 | // bit 4 means "flip x" for G_DrawTileScaled |
1209 | terminx | 1765 | if (orientation&4) |
2931 | helixhorne | 1766 | ang = 1024; |
1209 | terminx | 1767 | |
4249 | hendricks2 | 1768 | #ifdef SPLITSCREEN_MOD_HACKS |
2957 | helixhorne | 1769 | if (g_fakeMultiMode==2) |
2905 | helixhorne | 1770 | { |
2944 | helixhorne | 1771 | const int32_t sidebyside = (ud.screen_size!=0); |
1772 | |||
2905 | helixhorne | 1773 | // splitscreen HACK |
2944 | helixhorne | 1774 | orientation &= ~(1024|512|256); |
1775 | if (sidebyside) |
||
1776 | { |
||
1777 | orientation &= ~8; |
||
1778 | wx[(g_snum==0)] = (wx[0]+wx[1])/2 + 2; |
||
1779 | } |
||
1780 | else |
||
1781 | { |
||
1782 | orientation |= 8; |
||
1783 | if (g_snum==0) |
||
1784 | yofs = -(100<<16); |
||
1785 | wy[(g_snum==0)] = (wy[0]+wy[1])/2 + 2; |
||
1786 | } |
||
2905 | helixhorne | 1787 | } |
4249 | hendricks2 | 1788 | #endif |
2905 | helixhorne | 1789 | |
1820 | terminx | 1790 | #ifdef USE_OPENGL |
3346 | terminx | 1791 | if (getrendermode() >= REND_POLYMOST && usemodels && md_tilehasmodel(tilenum,p) >= 0) |
1209 | terminx | 1792 | y += (224-weapsc(224)); |
1793 | #endif |
||
2931 | helixhorne | 1794 | rotatesprite(weapsc(x<<16) + ((xoff-weapsc(xoff))<<16), |
3695 | helixhorne | 1795 | weapsc((y<<16) + g_dts_yadd) + ((200-weapsc(200))<<16) + yofs, |
2931 | helixhorne | 1796 | weapsc(65536L),ang,tilenum,shade,p,(2|orientation), |
2944 | helixhorne | 1797 | wx[0],wy[0], wx[1],wy[1]); |
1209 | terminx | 1798 | } |
1799 | |||
2917 | helixhorne | 1800 | static void G_DrawWeaponTile(int32_t x, int32_t y, int32_t tilenum, int32_t shade, |
1801 | int32_t orientation, int32_t p, uint8_t slot) |
||
1209 | terminx | 1802 | { |
1946 | hendricks2 | 1803 | static int32_t shadef[2] = {0, 0}, palf[2] = {0, 0}; |
1657 | terminx | 1804 | |
1946 | hendricks2 | 1805 | // sanity checking the slot value |
1806 | if (slot > 1) |
||
1807 | slot = 1; |
||
1808 | |||
1657 | terminx | 1809 | // basic fading between player weapon shades |
1946 | hendricks2 | 1810 | if (shadef[slot] != shade && (!p || palf[slot] == p)) |
1657 | terminx | 1811 | { |
1946 | hendricks2 | 1812 | shadef[slot] += (shade-shadef[slot])>>2; |
1657 | terminx | 1813 | |
1946 | hendricks2 | 1814 | if (!((shade-shadef[slot])>>2)) |
4392 | helixhorne | 1815 | shadef[slot] = logapproach(shadef[slot], shade); |
1657 | terminx | 1816 | } |
1817 | else |
||
1946 | hendricks2 | 1818 | shadef[slot] = shade; |
1657 | terminx | 1819 | |
1946 | hendricks2 | 1820 | palf[slot] = p; |
1657 | terminx | 1821 | |
1625 | terminx | 1822 | switch (ud.drawweapon) |
1823 | { |
||
1824 | case 1: |
||
3695 | helixhorne | 1825 | #ifdef USE_OPENGL |
1826 | if (getrendermode()>=REND_POLYMOST) |
||
1827 | if (tilenum >= CHAINGUN+1 && tilenum <= CHAINGUN+4) |
||
1828 | if (!usemodels || md_tilehasmodel(tilenum,p) < 0) |
||
1829 | { |
||
1830 | // HACK: Draw the upper part of the chaingun two screen |
||
1831 | // pixels (not texels; multiplied by weapon scale) lower |
||
1832 | // first, preventing ugly horizontal seam. |
||
1833 | g_dts_yadd = (65536*2*200)/ydim; |
||
1834 | G_DrawTileScaled(x,y,tilenum,shadef[slot],orientation,p); |
||
1835 | g_dts_yadd = 0; |
||
1836 | } |
||
1837 | #endif |
||
1946 | hendricks2 | 1838 | G_DrawTileScaled(x,y,tilenum,shadef[slot],orientation,p); |
1625 | terminx | 1839 | return; |
3695 | helixhorne | 1840 | |
1625 | terminx | 1841 | case 2: |
2945 | helixhorne | 1842 | { |
1843 | const DukePlayer_t *const ps = g_player[screenpeek].ps; |
||
1844 | const int32_t sc = scale(65536,ud.statusbarscale,100); |
||
1845 | |||
3695 | helixhorne | 1846 | if ((unsigned)hudweap.cur < MAX_WEAPONS && hudweap.cur != KNEE_WEAPON) |
2945 | helixhorne | 1847 | rotatesprite_win(160<<16,(180+(ps->weapon_pos*ps->weapon_pos))<<16, |
3408 | helixhorne | 1848 | sc,0,hudweap.cur==GROW_WEAPON?GROWSPRITEICON:WeaponPickupSprites[hudweap.cur], |
2318 | helixhorne | 1849 | 0,0,2); |
3695 | helixhorne | 1850 | return; |
1209 | terminx | 1851 | } |
2945 | helixhorne | 1852 | } |
1209 | terminx | 1853 | } |
1854 | |||
1611 | terminx | 1855 | static int32_t P_DisplayKnee(int32_t gs,int32_t snum) |
1209 | terminx | 1856 | { |
2917 | helixhorne | 1857 | static const int8_t knee_y[] = {0,-8,-16,-32,-64,-84,-108,-108,-108,-72,-32,-8}; |
2518 | helixhorne | 1858 | int32_t looking_arc, pal; |
1209 | terminx | 1859 | |
2917 | helixhorne | 1860 | const DukePlayer_t *const ps = g_player[snum].ps; |
1209 | terminx | 1861 | |
3436 | helixhorne | 1862 | if (ps->knee_incs == 0 || ps->knee_incs >= ARRAY_SIZE(knee_y) || sprite[ps->i].extra <= 0) |
1863 | return 0; |
||
1209 | terminx | 1864 | |
2917 | helixhorne | 1865 | looking_arc = knee_y[ps->knee_incs] + klabs(ps->look_ang)/9; |
1209 | terminx | 1866 | |
2917 | helixhorne | 1867 | looking_arc -= (ps->hard_landing<<3); |
1868 | |||
3353 | helixhorne | 1869 | pal = P_GetHudPal(ps); |
2518 | helixhorne | 1870 | if (pal == 0) |
2917 | helixhorne | 1871 | pal = ps->palookup; |
1209 | terminx | 1872 | |
2917 | helixhorne | 1873 | G_DrawTileScaled(105+(g_player[snum].sync->avel>>4)-(ps->look_ang>>1)+(knee_y[ps->knee_incs]>>2), |
1874 | looking_arc+280-((ps->horiz-ps->horizoff)>>4),KNEE,gs,4+DRAWEAP_CENTER,pal); |
||
1209 | terminx | 1875 | |
1876 | return 1; |
||
1877 | } |
||
1878 | |||
1611 | terminx | 1879 | static int32_t P_DisplayKnuckles(int32_t gs,int32_t snum) |
1209 | terminx | 1880 | { |
2917 | helixhorne | 1881 | static const int8_t knuckle_frames[] = {0,1,2,2,3,3,3,2,2,1,0}; |
2518 | helixhorne | 1882 | int32_t looking_arc, pal; |
1209 | terminx | 1883 | |
2917 | helixhorne | 1884 | const DukePlayer_t *const ps = g_player[snum].ps; |
1209 | terminx | 1885 | |
3673 | hendricks2 | 1886 | if (ps->knuckle_incs == 0 || (unsigned) (ps->knuckle_incs>>1) >= ARRAY_SIZE(knuckle_frames) || sprite[ps->i].extra <= 0) |
3436 | helixhorne | 1887 | return 0; |
1209 | terminx | 1888 | |
2917 | helixhorne | 1889 | looking_arc = klabs(ps->look_ang)/9; |
1209 | terminx | 1890 | |
2917 | helixhorne | 1891 | looking_arc -= (ps->hard_landing<<3); |
1209 | terminx | 1892 | |
3353 | helixhorne | 1893 | pal = P_GetHudPal(ps); |
1209 | terminx | 1894 | |
2917 | helixhorne | 1895 | G_DrawTileScaled(160+(g_player[snum].sync->avel>>4)-(ps->look_ang>>1), |
1896 | looking_arc+180-((ps->horiz-ps->horizoff)>>4), |
||
1897 | CRACKKNUCKLES+knuckle_frames[ps->knuckle_incs>>1],gs,4+DRAWEAP_CENTER,pal); |
||
1898 | |||
1209 | terminx | 1899 | return 1; |
1900 | } |
||
1901 | |||
3955 | helixhorne | 1902 | #if !defined LUNATIC |
1903 | // Set C-CON's WEAPON and WORKSLIKE gamevars. |
||
3413 | helixhorne | 1904 | void P_SetWeaponGamevars(int32_t snum, const DukePlayer_t *p) |
1905 | { |
||
1906 | Gv_SetVar(g_iWeaponVarID, p->curr_weapon, p->i, snum); |
||
1907 | Gv_SetVar(g_iWorksLikeVarID, |
||
1908 | ((unsigned)p->curr_weapon < MAX_WEAPONS) ? PWEAPON(snum, p->curr_weapon, WorksLike) : -1, |
||
1909 | p->i, snum); |
||
3955 | helixhorne | 1910 | } |
3413 | helixhorne | 1911 | #endif |
1912 | |||
4227 | helixhorne | 1913 | static void P_FireWeapon(int32_t snum) |
1209 | terminx | 1914 | { |
4227 | helixhorne | 1915 | int32_t i; |
1916 | DukePlayer_t *const p = g_player[snum].ps; |
||
1209 | terminx | 1917 | |
2656 | terminx | 1918 | if (VM_OnEvent(EVENT_DOFIRE, p->i, snum, -1, 0) == 0) |
1209 | terminx | 1919 | { |
1920 | if (p->weapon_pos != 0) return; |
||
1921 | |||
3328 | helixhorne | 1922 | if (PWEAPON(snum, p->curr_weapon, WorksLike) != KNEE_WEAPON) |
1209 | terminx | 1923 | p->ammo_amount[p->curr_weapon]--; |
1924 | |||
3328 | helixhorne | 1925 | if (PWEAPON(snum, p->curr_weapon, FireSound) > 0) |
1926 | A_PlaySound(PWEAPON(snum, p->curr_weapon, FireSound),p->i); |
||
1209 | terminx | 1927 | |
3413 | helixhorne | 1928 | P_SetWeaponGamevars(snum, p); |
3328 | helixhorne | 1929 | // OSD_Printf("doing %d %d %d\n",PWEAPON(snum, p->curr_weapon, Shoots),p->curr_weapon,snum); |
1930 | A_Shoot(p->i,PWEAPON(snum, p->curr_weapon, Shoots)); |
||
1611 | terminx | 1931 | |
3328 | helixhorne | 1932 | for (i=PWEAPON(snum, p->curr_weapon, ShotsPerBurst)-1; i > 0; i--) |
1209 | terminx | 1933 | { |
3328 | helixhorne | 1934 | if (PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_FIREEVERYOTHER) |
1209 | terminx | 1935 | { |
1936 | // this makes the projectiles fire on a delay from player code |
||
3328 | helixhorne | 1937 | actor[p->i].t_data[7] = (PWEAPON(snum, p->curr_weapon, ShotsPerBurst))<<1; |
1209 | terminx | 1938 | } |
1939 | else |
||
1940 | { |
||
3328 | helixhorne | 1941 | if (PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_AMMOPERSHOT && |
1942 | PWEAPON(snum, p->curr_weapon, WorksLike) != KNEE_WEAPON) |
||
1209 | terminx | 1943 | { |
1944 | if (p->ammo_amount[p->curr_weapon] > 0) |
||
1945 | p->ammo_amount[p->curr_weapon]--; |
||
1946 | else break; |
||
1947 | } |
||
3955 | helixhorne | 1948 | |
3328 | helixhorne | 1949 | A_Shoot(p->i,PWEAPON(snum, p->curr_weapon, Shoots)); |
1209 | terminx | 1950 | } |
1951 | } |
||
1952 | |||
3328 | helixhorne | 1953 | if (!(PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_NOVISIBLE)) |
1209 | terminx | 1954 | { |
1336 | terminx | 1955 | #ifdef POLYMER |
1312 | terminx | 1956 | spritetype *s = &sprite[p->i]; |
1402 | terminx | 1957 | int32_t x = ((sintable[(s->ang+512)&2047])>>7), y = ((sintable[(s->ang)&2047])>>7); |
1312 | terminx | 1958 | |
1402 | terminx | 1959 | s->x += x; |
1960 | s->y += y; |
||
3328 | helixhorne | 1961 | G_AddGameLight(0, p->i, PHEIGHT, 8192, PWEAPON(snum, p->curr_weapon, FlashColor),PR_LIGHT_PRIO_MAX_GAME); |
1625 | terminx | 1962 | actor[p->i].lightcount = 2; |
1402 | terminx | 1963 | s->x -= x; |
1964 | s->y -= y; |
||
1336 | terminx | 1965 | #endif // POLYMER |
1409 | terminx | 1966 | p->visibility = 0; |
1209 | terminx | 1967 | } |
1968 | } |
||
1969 | } |
||
1970 | |||
4227 | helixhorne | 1971 | static void P_DoWeaponSpawn(int32_t snum) |
1209 | terminx | 1972 | { |
4227 | helixhorne | 1973 | int32_t j; |
1974 | const DukePlayer_t *const p = g_player[snum].ps; |
||
1209 | terminx | 1975 | |
3955 | helixhorne | 1976 | // NOTE: For the 'Spawn' member, 0 means 'none', too (originally so, |
1977 | // i.e. legacy). The check for <0 was added to the check because mod |
||
1978 | // authors (rightly) assumed that -1 is the no-op value. |
||
3328 | helixhorne | 1979 | if (PWEAPON(snum, p->curr_weapon, Spawn) <= 0) // <=0 : AMC TC beta/RC2 has WEAPONx_SPAWN -1 |
1209 | terminx | 1980 | return; |
1981 | |||
3328 | helixhorne | 1982 | j = A_Spawn(p->i, PWEAPON(snum, p->curr_weapon, Spawn)); |
1209 | terminx | 1983 | |
3328 | helixhorne | 1984 | if ((PWEAPON(snum, p->curr_weapon, Flags) & WEAPON_SPAWNTYPE3)) |
1209 | terminx | 1985 | { |
1986 | // like chaingun shells |
||
1987 | sprite[j].ang += 1024; |
||
1988 | sprite[j].ang &= 2047; |
||
1989 | sprite[j].xvel += 32; |
||
1990 | sprite[j].z += (3<<8); |
||
1991 | } |
||
1992 | |||
1993 | A_SetSprite(j,CLIPMASK0); |
||
1994 | |||
1995 | } |
||
1996 | |||
1611 | terminx | 1997 | void P_DisplayScuba(int32_t snum) |
1209 | terminx | 1998 | { |
1999 | if (g_player[snum].ps->scuba_on) |
||
2000 | { |
||
3353 | helixhorne | 2001 | int32_t p = P_GetHudPal(g_player[snum].ps); |
2524 | helixhorne | 2002 | |
2933 | helixhorne | 2003 | g_snum = snum; |
3688 | terminx | 2004 | #ifdef USE_OPENGL |
2005 | if (getrendermode() >= REND_POLYMOST) |
||
2006 | G_DrawTileScaled(44, (200-tilesizy[SCUBAMASK]), SCUBAMASK, 0, 2+16+DRAWEAP_CENTER, p); |
||
2007 | #endif |
||
2933 | helixhorne | 2008 | G_DrawTileScaled(43, (200-tilesizy[SCUBAMASK]), SCUBAMASK, 0, 2+16+DRAWEAP_CENTER, p); |
2009 | G_DrawTileScaled(320-43, (200-tilesizy[SCUBAMASK]), SCUBAMASK, 0, 2+4+16+DRAWEAP_CENTER, p); |
||
1209 | terminx | 2010 | } |
2011 | } |
||
2012 | |||
1611 | terminx | 2013 | static int32_t P_DisplayTip(int32_t gs,int32_t snum) |
1209 | terminx | 2014 | { |
3436 | helixhorne | 2015 | int32_t p,looking_arc, tipy; |
1209 | terminx | 2016 | |
2917 | helixhorne | 2017 | static const int16_t tip_y[] = { |
2018 | 0,-8,-16,-32,-64, |
||
2019 | -84,-108,-108,-108,-108, |
||
2020 | -108,-108,-108,-108,-108, |
||
2021 | -108,-96,-72,-64,-32, |
||
3630 | helixhorne | 2022 | -16, /* EDuke32: */ 0, 16, 32, 48, |
2023 | // At y coord 64, the hand is already not shown. |
||
2917 | helixhorne | 2024 | }; |
1209 | terminx | 2025 | |
2917 | helixhorne | 2026 | const DukePlayer_t *const ps = g_player[snum].ps; |
1209 | terminx | 2027 | |
3630 | helixhorne | 2028 | if (ps->tipincs == 0) |
3436 | helixhorne | 2029 | return 0; |
1209 | terminx | 2030 | |
3630 | helixhorne | 2031 | // Report that the tipping hand has been drawn so that the otherwise |
2032 | // selected weapon is not drawn. |
||
2033 | if (ps->tipincs >= ARRAY_SIZE(tip_y)) |
||
2034 | return 1; |
||
2035 | |||
2917 | helixhorne | 2036 | looking_arc = klabs(ps->look_ang)/9; |
2037 | looking_arc -= (ps->hard_landing<<3); |
||
2038 | |||
3353 | helixhorne | 2039 | p = P_GetHudPal(ps); |
2917 | helixhorne | 2040 | |
3436 | helixhorne | 2041 | tipy = tip_y[ps->tipincs]>>1; |
2171 | helixhorne | 2042 | |
2917 | helixhorne | 2043 | G_DrawTileScaled(170+(g_player[snum].sync->avel>>4)-(ps->look_ang>>1), |
2044 | tipy+looking_arc+240-((ps->horiz-ps->horizoff)>>4), |
||
2045 | TIP+((26-ps->tipincs)>>4),gs,DRAWEAP_CENTER,p); |
||
1209 | terminx | 2046 | |
2047 | return 1; |
||
2048 | } |
||
2049 | |||
1611 | terminx | 2050 | static int32_t P_DisplayAccess(int32_t gs,int32_t snum) |
1209 | terminx | 2051 | { |
2639 | helixhorne | 2052 | static const int16_t access_y[] = { |
2053 | 0,-8,-16,-32,-64, |
||
2054 | -84,-108,-108,-108,-108, |
||
2055 | -108,-108,-108,-108,-108, |
||
2917 | helixhorne | 2056 | -108,-96,-72,-64,-32, |
2057 | -16 |
||
2639 | helixhorne | 2058 | }; |
2059 | |||
1625 | terminx | 2060 | int32_t looking_arc, p = 0; |
2917 | helixhorne | 2061 | const DukePlayer_t *const ps = g_player[snum].ps; |
1209 | terminx | 2062 | |
3436 | helixhorne | 2063 | if (ps->access_incs == 0 || ps->access_incs >= ARRAY_SIZE(access_y) || sprite[ps->i].extra <= 0) |
2064 | return 0; |
||
1209 | terminx | 2065 | |
2917 | helixhorne | 2066 | looking_arc = access_y[ps->access_incs] + klabs(ps->look_ang)/9 - |
2067 | (ps->hard_landing<<3); |
||
1209 | terminx | 2068 | |
2917 | helixhorne | 2069 | if (ps->access_spritenum >= 0) |
2070 | p = sprite[ps->access_spritenum].pal; |
||
1625 | terminx | 2071 | |
2917 | helixhorne | 2072 | if ((ps->access_incs-3) > 0 && (ps->access_incs-3)>>3) |
2339 | helixhorne | 2073 | { |
2074 | guniqhudid = 200; |
||
2917 | helixhorne | 2075 | G_DrawTileScaled(170+(g_player[snum].sync->avel>>4)-(ps->look_ang>>1)+(access_y[ps->access_incs]>>2), |
2076 | looking_arc+266-((ps->horiz-ps->horizoff)>>4),HANDHOLDINGLASER+(ps->access_incs>>3), |
||
2077 | gs,DRAWEAP_CENTER,p); |
||
2339 | helixhorne | 2078 | guniqhudid = 0; |
2079 | } |
||
1209 | terminx | 2080 | else |
2339 | helixhorne | 2081 | { |
2082 | guniqhudid = 201; |
||
2917 | helixhorne | 2083 | G_DrawTileScaled(170+(g_player[snum].sync->avel>>4)-(ps->look_ang>>1)+(access_y[ps->access_incs]>>2), |
2084 | looking_arc+266-((ps->horiz-ps->horizoff)>>4),HANDHOLDINGACCESS,gs,4+DRAWEAP_CENTER,p); |
||
2339 | helixhorne | 2085 | guniqhudid = 0; |
2086 | } |
||
1209 | terminx | 2087 | |
2088 | return 1; |
||
2089 | } |
||
2090 | |||
2091 | |||
2092 | static int32_t fistsign; |
||
2093 | |||
2094 | void P_DisplayWeapon(int32_t snum) |
||
2095 | { |
||
2096 | int32_t gun_pos, looking_arc, cw; |
||
2097 | int32_t weapon_xoffset, i, j; |
||
2098 | int32_t o = 0,pal = 0; |
||
2876 | helixhorne | 2099 | DukePlayer_t *const p = g_player[snum].ps; |
3353 | helixhorne | 2100 | const uint8_t *const kb = &p->kickback_pic; |
1209 | terminx | 2101 | int32_t gs; |
2102 | |||
2905 | helixhorne | 2103 | g_snum = snum; |
2104 | |||
1209 | terminx | 2105 | looking_arc = klabs(p->look_ang)/9; |
2106 | |||
2107 | gs = sprite[p->i].shade; |
||
2108 | if (gs > 24) gs = 24; |
||
2109 | |||
1625 | terminx | 2110 | if (p->newowner >= 0 || ud.camerasprite >= 0 || p->over_shoulder_on > 0 || (sprite[p->i].pal != 1 && sprite[p->i].extra <= 0) || |
1677 | terminx | 2111 | P_DisplayFist(gs,snum) || P_DisplayKnuckles(gs,snum) || P_DisplayTip(gs,snum) || P_DisplayAccess(gs,snum)) |
1209 | terminx | 2112 | return; |
2113 | |||
1611 | terminx | 2114 | P_DisplayKnee(gs,snum); |
1209 | terminx | 2115 | |
2116 | gun_pos = 80-(p->weapon_pos*p->weapon_pos); |
||
2117 | |||
2118 | weapon_xoffset = (160)-90; |
||
2119 | |||
2120 | if (ud.weaponsway) |
||
2121 | { |
||
2122 | weapon_xoffset -= (sintable[((p->weapon_sway>>1)+512)&2047]/(1024+512)); |
||
2123 | |||
2124 | if (sprite[p->i].xrepeat < 32) |
||
2125 | gun_pos -= klabs(sintable[(p->weapon_sway<<2)&2047]>>9); |
||
2126 | else gun_pos -= klabs(sintable[(p->weapon_sway>>1)&2047]>>10); |
||
2127 | } |
||
2128 | else gun_pos -= 16; |
||
2129 | |||
2130 | weapon_xoffset -= 58 + p->weapon_ang; |
||
2131 | gun_pos -= (p->hard_landing<<3); |
||
2132 | |||
2133 | if (p->last_weapon >= 0) |
||
3328 | helixhorne | 2134 | cw = PWEAPON(snum, p->last_weapon, WorksLike); |
1209 | terminx | 2135 | else |
3328 | helixhorne | 2136 | cw = PWEAPON(snum, p->curr_weapon, WorksLike); |
1209 | terminx | 2137 | |
3408 | helixhorne | 2138 | hudweap.gunposy=gun_pos; |
2139 | hudweap.lookhoriz=looking_arc; |
||
2140 | hudweap.cur=cw; |
||
2141 | hudweap.gunposx=weapon_xoffset; |
||
2142 | hudweap.shade=gs; |
||
2143 | hudweap.count=*kb; |
||
2144 | hudweap.lookhalfang=p->look_ang>>1; |
||
1209 | terminx | 2145 | |
2656 | terminx | 2146 | if (VM_OnEvent(EVENT_DISPLAYWEAPON, p->i, screenpeek, -1, 0) == 0) |
1209 | terminx | 2147 | { |
2148 | j = 14-p->quick_kick; |
||
2149 | if (j != 14 || p->last_quick_kick) |
||
2150 | { |
||
3353 | helixhorne | 2151 | pal = P_GetHudPal(p); |
2518 | helixhorne | 2152 | if (pal == 0) |
2153 | pal = p->palookup; |
||
1209 | terminx | 2154 | |
2155 | guniqhudid = 100; |
||
2156 | if (j < 6 || j > 12) |
||
2157 | G_DrawTileScaled(weapon_xoffset+80-(p->look_ang>>1), |
||
2917 | helixhorne | 2158 | looking_arc+250-gun_pos,KNEE,gs,o|4|DRAWEAP_CENTER,pal); |
1209 | terminx | 2159 | else G_DrawTileScaled(weapon_xoffset+160-16-(p->look_ang>>1), |
2934 | helixhorne | 2160 | looking_arc+214-gun_pos,KNEE+1,gs,o|4|DRAWEAP_CENTER,pal); |
1209 | terminx | 2161 | guniqhudid = 0; |
2162 | } |
||
2163 | |||
2164 | if (sprite[p->i].xrepeat < 40) |
||
2165 | { |
||
3353 | helixhorne | 2166 | pal = P_GetHudPal(p); |
2934 | helixhorne | 2167 | |
1209 | terminx | 2168 | if (p->jetpack_on == 0) |
2169 | { |
||
2170 | i = sprite[p->i].xvel; |
||
3614 | terminx | 2171 | looking_arc += 32-(i>>3); |
2172 | fistsign += i>>3; |
||
1209 | terminx | 2173 | } |
2934 | helixhorne | 2174 | |
1209 | terminx | 2175 | cw = weapon_xoffset; |
2176 | weapon_xoffset += sintable[(fistsign)&2047]>>10; |
||
2934 | helixhorne | 2177 |