diff --git a/source/games/duke/src/player_d.cpp b/source/games/duke/src/player_d.cpp index 9719fb646..f670c6b3b 100644 --- a/source/games/duke/src/player_d.cpp +++ b/source/games/duke/src/player_d.cpp @@ -80,6 +80,980 @@ void incur_damage_d(struct player_struct* p) } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void shootfireball(int i, int p, int sx, int sy, int sz, int sa) +{ + spritetype* const s = &sprite[i]; + int vel, zvel; + + if (s->extra >= 0) + s->shade = -96; + + sz -= (4 << 7); + if (sprite[i].picnum != BOSS5) + vel = 840; + else { + vel = 968; + sz += 6144; + } + + if (p < 0) + { + sa += 16 - (krand() & 31); + int scratch; + int j = findplayer(s, &scratch); + zvel = (((ps[j].oposz - sz + (3 << 8))) * vel) / ldist(&sprite[ps[j].i], s); + } + else + { + zvel = -mulscale16(ps[p].horizon.sum().asq16(), 98); + sx += sintable[(sa + 860) & 0x7FF] / 448; + sy += sintable[(sa + 348) & 0x7FF] / 448; + sz += (3 << 8); + } + + int sizx = 18; + int sizy = 18; + if (p >= 0) + { + sizx = 7; + sizy = 7; + } + + int j = EGS(s->sectnum, sx, sy, sz, FIREBALL, -127, sizx, sizy, sa, vel, zvel, i, (short)4); + auto spr = &sprite[j]; + spr->extra += (krand() & 7); + if (sprite[i].picnum == BOSS5 || p >= 0) + { + spr->xrepeat = 40; + spr->yrepeat = 40; + } + spr->yvel = p; + spr->cstat = 128; + spr->clipdist = 4; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void shootflamethrowerflame(int i, int p, int sx, int sy, int sz, int sa) +{ + spritetype* const s = &sprite[i]; + int vel, zvel; + + if (s->extra >= 0) + s->shade = -96; + vel = 400; + + int k = -1; + if (p < 0) + { + int x; + int j = findplayer(s, &x); + sa = getangle(ps[j].oposx - sx, ps[j].oposy - sy); + + if (sprite[i].picnum == BOSS5) + { + vel = 528; + sz += 6144; + } + else if (sprite[i].picnum == BOSS3) + sz -= 8192; + + int l = ldist(&sprite[ps[j].i], s); + if (l != 0) + zvel = ((ps[j].oposz - sz) * vel) / l; + + if (badguy(s) && (s->hitag & face_player_smart) != 0) + sa = (short)(s->ang + (krand() & 31) - 16); + + if (sector[s->sectnum].lotag == 2 && (krand() % 5) == 0) + k = fi.spawn(i, WATERBUBBLE); + } + else + { + zvel = -mulscale16(ps[p].horizon.sum().asq16(), 81); + if (sprite[ps[p].i].xvel != 0) + vel = (int)((((512 - (1024 + - abs(abs(getangle(sx - ps[p].oposx, sy - ps[p].oposy) - sa) - 1024))) + * 0.001953125f) * sprite[ps[p].i].xvel) + 400); + if (sector[s->sectnum].lotag == 2 && (krand() % 5) == 0) + k = fi.spawn(i, WATERBUBBLE); + } + + if (k == -1) + { + k = fi.spawn(i, FLAMETHROWERFLAME); + sprite[k].xvel = (short)vel; + sprite[k].zvel = (short)zvel; + } + + sprite[k].x = sx + sintable[(sa + 630) & 0x7FF] / 448; + sprite[k].y = sy + sintable[(sa + 112) & 0x7FF] / 448; + sprite[k].z = sz - 256; + sprite[k].sectnum = s->sectnum; + sprite[k].cstat = 0x80; + sprite[k].ang = sa; + sprite[k].xrepeat = 2; + sprite[k].yrepeat = 2; + sprite[k].clipdist = 40; + sprite[k].yvel = p; + sprite[k].owner = (short)i; + + if (p == -1) + { + if (sprite[i].picnum == BOSS5) + { + sprite[k].x -= sintable[sa & 2047] / 56; + sprite[k].y -= sintable[(sa + 1024 + 512) & 2047] / 56; + sprite[k].xrepeat = 10; + sprite[k].yrepeat = 10; + } + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void shootbloodsplat(int i, int p, int sx, int sy, int sz, int sa, int atwith) +{ + spritetype* const s = &sprite[i]; + int sect = s->sectnum; + int zvel; + short hitsect, hitspr, hitwall, k; + int hitx, hity, hitz; + + if (p >= 0) + sa += 64 - (krand() & 127); + else sa += 1024 + 64 - (krand() & 127); + zvel = 1024 - (krand() & 2047); + + + hitscan(sx, sy, sz, sect, + sintable[(sa + 512) & 2047], + sintable[sa & 2047], zvel << 6, + &hitsect, &hitwall, &hitspr, &hitx, &hity, &hitz, CLIPMASK1); + + // oh my... + if (FindDistance2D(sx - hitx, sy - hity) < 1024 && + (hitwall >= 0 && wall[hitwall].overpicnum != BIGFORCE) && + ((wall[hitwall].nextsector >= 0 && hitsect >= 0 && + sector[wall[hitwall].nextsector].lotag == 0 && + sector[hitsect].lotag == 0 && + sector[wall[hitwall].nextsector].lotag == 0 && + (sector[hitsect].floorz - sector[wall[hitwall].nextsector].floorz) > (16 << 8)) || + (wall[hitwall].nextsector == -1 && sector[hitsect].lotag == 0))) + { + if ((wall[hitwall].cstat & 16) == 0) + { + if (wall[hitwall].nextsector >= 0) + { + SectIterator it(wall[hitwall].nextsector); + while ((k = it.NextIndex()) >= 0) + { + if (sprite[k].statnum == 3 && sprite[k].lotag == 13) + return; + } + } + + if (wall[hitwall].nextwall >= 0 && + wall[wall[hitwall].nextwall].hitag != 0) + return; + + if (wall[hitwall].hitag == 0) + { + k = fi.spawn(i, atwith); + sprite[k].xvel = -12; + sprite[k].ang = getangle(wall[hitwall].x - wall[wall[hitwall].point2].x, wall[hitwall].y - wall[wall[hitwall].point2].y) + 512; + sprite[k].x = hitx; + sprite[k].y = hity; + sprite[k].z = hitz; + sprite[k].cstat |= (krand() & 4); + ssp(k, CLIPMASK0); + setsprite(k, sprite[k].x, sprite[k].y, sprite[k].z); + if (s->picnum == OOZFILTER || s->picnum == NEWBEAST) + sprite[k].pal = 6; + } + } + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void shootknee(int i, int p, int sx, int sy, int sz, int sa) +{ + spritetype* const s = &sprite[i]; + int sect = s->sectnum; + int zvel; + short hitsect, hitspr, hitwall, j, k; + int hitx, hity, hitz; + + if (p >= 0) + { + zvel = -ps[p].horizon.sum().asq16() >> 11; + sz += (6 << 8); + sa += 15; + } + else + { + int x; + j = ps[findplayer(s, &x)].i; + zvel = ((sprite[j].z - sz) << 8) / (x + 1); + sa = getangle(sprite[j].x - sx, sprite[j].y - sy); + } + + hitscan(sx, sy, sz, sect, + sintable[(sa + 512) & 2047], + sintable[sa & 2047], zvel << 6, + &hitsect, &hitwall, &hitspr, &hitx, &hity, &hitz, CLIPMASK1); + + + if (hitsect < 0) return; + + if ((abs(sx - hitx) + abs(sy - hity)) < 1024) + { + if (hitwall >= 0 || hitspr >= 0) + { + j = EGS(hitsect, hitx, hity, hitz, KNEE, -15, 0, 0, sa, 32, 0, i, 4); + sprite[j].extra += (krand() & 7); + if (p >= 0) + { + k = fi.spawn(j, SMALLSMOKE); + sprite[k].z -= (8 << 8); + S_PlayActorSound(KICK_HIT, j); + } + + if (p >= 0 && ps[p].steroids_amount > 0 && ps[p].steroids_amount < 400) + sprite[j].extra += (max_player_health >> 2); + + if (hitspr >= 0 && sprite[hitspr].picnum != ACCESSSWITCH && sprite[hitspr].picnum != ACCESSSWITCH2) + { + fi.checkhitsprite(hitspr, j); + if (p >= 0) fi.checkhitswitch(p, hitspr, 1); + } + + else if (hitwall >= 0) + { + if (wall[hitwall].cstat & 2) + if (wall[hitwall].nextsector >= 0) + if (hitz >= (sector[wall[hitwall].nextsector].floorz)) + hitwall = wall[hitwall].nextwall; + + if (hitwall >= 0 && wall[hitwall].picnum != ACCESSSWITCH && wall[hitwall].picnum != ACCESSSWITCH2) + { + fi.checkhitwall(j, hitwall, hitx, hity, hitz, KNEE); + if (p >= 0) fi.checkhitswitch(p, hitwall, 0); + } + } + } + else if (p >= 0 && zvel > 0 && sector[hitsect].lotag == 1) + { + j = fi.spawn(ps[p].i, WATERSPLASH2); + sprite[j].x = hitx; + sprite[j].y = hity; + sprite[j].ang = ps[p].angle.ang.asbuild(); // Total tweek + sprite[j].xvel = 32; + ssp(i, CLIPMASK0); + sprite[j].xvel = 0; + + } + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void shootweapon(int i, int p, int sx, int sy, int sz, int sa, int atwith) +{ + spritetype* const s = &sprite[i]; + int sect = s->sectnum; + int zvel; + short hitsect, hitspr, hitwall, l, j, k; + int hitx, hity, hitz; + + if (s->extra >= 0) s->shade = -96; + + if (p >= 0) + { + SetGameVarID(g_iAimAngleVarID, AUTO_AIM_ANGLE, i, p); + OnEvent(EVENT_GETAUTOAIMANGLE, i, p, -1); + j = -1; + if (GetGameVarID(g_iAimAngleVarID, i, p) > 0) + { + j = aim(s, GetGameVarID(g_iAimAngleVarID, i, p)); + } + + if (j >= 0) + { + int dal = ((sprite[j].xrepeat * tilesiz[sprite[j].picnum].y) << 1) + (5 << 8); + switch (sprite[j].picnum) + { + case GREENSLIME: + case GREENSLIME + 1: + case GREENSLIME + 2: + case GREENSLIME + 3: + case GREENSLIME + 4: + case GREENSLIME + 5: + case GREENSLIME + 6: + case GREENSLIME + 7: + case ROTATEGUN: + dal -= (8 << 8); + break; + } + zvel = ((sprite[j].z - sz - dal) << 8) / ldist(&sprite[ps[p].i], &sprite[j]); + sa = getangle(sprite[j].x - sx, sprite[j].y - sy); + } + + if (isWW2GI()) + { + int angRange = 32; + int zRange = 256; + SetGameVarID(g_iAngRangeVarID, 32, i, p); + SetGameVarID(g_iZRangeVarID, 256, i, p); + OnEvent(EVENT_GETSHOTRANGE, i, p, -1); + angRange = GetGameVarID(g_iAngRangeVarID, i, p); + zRange = GetGameVarID(g_iZRangeVarID, i, p); + + sa += (angRange / 2) - (krand() & (angRange - 1)); + if (j == -1) + { + // no target + zvel = -ps[p].horizon.sum().asq16() >> 11; + } + zvel += (zRange / 2) - (krand() & (zRange - 1)); + } + else if (j == -1) + { + sa += 16 - (krand() & 31); + zvel = -ps[p].horizon.sum().asq16() >> 11; + zvel += 128 - (krand() & 255); + } + + sz -= (2 << 8); + } + else + { + int x; + j = findplayer(s, &x); + sz -= (4 << 8); + zvel = ((ps[j].posz - sz) << 8) / (ldist(&sprite[ps[j].i], s)); + if (s->picnum != BOSS1) + { + zvel += 128 - (krand() & 255); + sa += 32 - (krand() & 63); + } + else + { + zvel += 128 - (krand() & 255); + sa = getangle(ps[j].posx - sx, ps[j].posy - sy) + 64 - (krand() & 127); + } + } + + s->cstat &= ~257; + hitscan(sx, sy, sz, sect, + sintable[(sa + 512) & 2047], + sintable[sa & 2047], + zvel << 6, &hitsect, &hitwall, &hitspr, &hitx, &hity, &hitz, CLIPMASK1); + s->cstat |= 257; + + if (hitsect < 0) return; + + if ((krand() & 15) == 0 && sector[hitsect].lotag == 2) + tracers(hitx, hity, hitz, sx, sy, sz, 8 - (ud.multimode >> 1)); + + if (p >= 0) + { + k = EGS(hitsect, hitx, hity, hitz, SHOTSPARK1, -15, 10, 10, sa, 0, 0, i, 4); + sprite[k].extra = ScriptCode[actorinfo[atwith].scriptaddress]; + sprite[k].extra += (krand() % 6); + + if (hitwall == -1 && hitspr == -1) + { + if (zvel < 0) + { + if (sector[hitsect].ceilingstat & 1) + { + sprite[k].xrepeat = 0; + sprite[k].yrepeat = 0; + return; + } + else + fi.checkhitceiling(hitsect); + } + fi.spawn(k, SMALLSMOKE); + } + + if (hitspr >= 0) + { + fi.checkhitsprite(hitspr, k); + if (sprite[hitspr].picnum == TILE_APLAYER && (ud.coop != 1 || ud.ffire == 1)) + { + l = fi.spawn(k, JIBS6); + sprite[k].xrepeat = sprite[k].yrepeat = 0; + sprite[l].z += (4 << 8); + sprite[l].xvel = 16; + sprite[l].xrepeat = sprite[l].yrepeat = 24; + sprite[l].ang += 64 - (krand() & 127); + } + else fi.spawn(k, SMALLSMOKE); + + if (p >= 0 && ( + sprite[hitspr].picnum == DIPSWITCH || + sprite[hitspr].picnum == DIPSWITCH + 1 || + sprite[hitspr].picnum == DIPSWITCH2 || + sprite[hitspr].picnum == DIPSWITCH2 + 1 || + sprite[hitspr].picnum == DIPSWITCH3 || + sprite[hitspr].picnum == DIPSWITCH3 + 1 || + sprite[hitspr].picnum == HANDSWITCH || + sprite[hitspr].picnum == HANDSWITCH + 1)) + { + fi.checkhitswitch(p, hitspr, 1); + return; + } + } + else if (hitwall >= 0) + { + fi.spawn(k, SMALLSMOKE); + + if (fi.isadoorwall(wall[hitwall].picnum) == 1) + goto SKIPBULLETHOLE; + if (p >= 0 && ( + wall[hitwall].picnum == DIPSWITCH || + wall[hitwall].picnum == DIPSWITCH + 1 || + wall[hitwall].picnum == DIPSWITCH2 || + wall[hitwall].picnum == DIPSWITCH2 + 1 || + wall[hitwall].picnum == DIPSWITCH3 || + wall[hitwall].picnum == DIPSWITCH3 + 1 || + wall[hitwall].picnum == HANDSWITCH || + wall[hitwall].picnum == HANDSWITCH + 1)) + { + fi.checkhitswitch(p, hitwall, 0); + return; + } + + if (wall[hitwall].hitag != 0 || (wall[hitwall].nextwall >= 0 && wall[wall[hitwall].nextwall].hitag != 0)) + goto SKIPBULLETHOLE; + + if (hitsect >= 0 && sector[hitsect].lotag == 0) + if (wall[hitwall].overpicnum != BIGFORCE) + if ((wall[hitwall].nextsector >= 0 && sector[wall[hitwall].nextsector].lotag == 0) || + (wall[hitwall].nextsector == -1 && sector[hitsect].lotag == 0)) + if ((wall[hitwall].cstat & 16) == 0) + { + if (wall[hitwall].nextsector >= 0) + { + SectIterator it(wall[hitwall].nextsector); + while ((l = it.NextIndex()) >= 0) + { + if (sprite[l].statnum == 3 && sprite[l].lotag == 13) + goto SKIPBULLETHOLE; + } + } + + StatIterator it(STAT_MISC); + while ((l = it.NextIndex()) >= 0) + { + if (sprite[l].picnum == BULLETHOLE) + if (dist(&sprite[l], &sprite[k]) < (12 + (krand() & 7))) + goto SKIPBULLETHOLE; + } + l = fi.spawn(k, BULLETHOLE); + sprite[l].xvel = -1; + sprite[l].ang = getangle(wall[hitwall].x - wall[wall[hitwall].point2].x, + wall[hitwall].y - wall[wall[hitwall].point2].y) + 512; + ssp(l, CLIPMASK0); + } + + SKIPBULLETHOLE: + + if (wall[hitwall].cstat & 2) + if (wall[hitwall].nextsector >= 0) + if (hitz >= (sector[wall[hitwall].nextsector].floorz)) + hitwall = wall[hitwall].nextwall; + + fi.checkhitwall(k, hitwall, hitx, hity, hitz, SHOTSPARK1); + } + } + else + { + k = EGS(hitsect, hitx, hity, hitz, SHOTSPARK1, -15, 24, 24, sa, 0, 0, i, 4); + sprite[k].extra = ScriptCode[actorinfo[atwith].scriptaddress]; + + if (hitspr >= 0) + { + fi.checkhitsprite(hitspr, k); + if (sprite[hitspr].picnum != TILE_APLAYER) + fi.spawn(k, SMALLSMOKE); + else sprite[k].xrepeat = sprite[k].yrepeat = 0; + } + else if (hitwall >= 0) { + + fi.checkhitwall(k, hitwall, hitx, hity, hitz, SHOTSPARK1); + } + } + + if ((krand() & 255) < 4) + { + vec3_t v{ hitx, hity, hitz }; + S_PlaySound3D(PISTOL_RICOCHET, k, &v); + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void shootstuff(int i, int p, int sx, int sy, int sz, int sa, int atwith) +{ + spritetype* const s = &sprite[i]; + int sect = s->sectnum; + int vel, zvel; + short l, j, scount; + + if (s->extra >= 0) s->shade = -96; + + scount = 1; + if (atwith == SPIT) vel = 292; + else + { + if (atwith == COOLEXPLOSION1) + { + if (s->picnum == BOSS2) vel = 644; + else vel = 348; + sz -= (4 << 7); + } + else + { + vel = 840; + sz -= (4 << 7); + } + } + + if (p >= 0) + { + j = aim(s, AUTO_AIM_ANGLE); + + if (j >= 0) + { + int dal = ((sprite[j].xrepeat * tilesiz[sprite[j].picnum].y) << 1) - (12 << 8); + zvel = ((sprite[j].z - sz - dal) * vel) / ldist(&sprite[ps[p].i], &sprite[j]); + sa = getangle(sprite[j].x - sx, sprite[j].y - sy); + } + else + zvel = -mulscale16(ps[p].horizon.sum().asq16(), 98); + } + else + { + int x; + j = findplayer(s, &x); + // sa = getangle(ps[j].oposx-sx,ps[j].oposy-sy); + sa += 16 - (krand() & 31); + zvel = (((ps[j].oposz - sz + (3 << 8))) * vel) / ldist(&sprite[ps[j].i], s); + } + + int oldzvel = zvel; + int sizx, sizy; + + if (atwith == SPIT) { sizx = 18; sizy = 18, sz -= (10 << 8); } + else + { + if (atwith == FIRELASER) + { + if (p >= 0) + { + + sizx = 34; + sizy = 34; + } + else + { + sizx = 18; + sizy = 18; + } + } + else + { + sizx = 18; + sizy = 18; + } + } + + if (p >= 0) sizx = 7, sizy = 7; + + while (scount > 0) + { + j = EGS(sect, sx, sy, sz, atwith, -127, sizx, sizy, sa, vel, zvel, i, 4); + sprite[j].extra += (krand() & 7); + + if (atwith == COOLEXPLOSION1) + { + sprite[j].shade = 0; + if (s->picnum == BOSS2) + { + l = sprite[j].xvel; + sprite[j].xvel = 1024; + ssp(j, CLIPMASK0); + sprite[j].xvel = l; + sprite[j].ang += 128 - (krand() & 255); + } + } + + sprite[j].cstat = 128; + sprite[j].clipdist = 4; + + sa = s->ang + 32 - (krand() & 63); + zvel = oldzvel + 512 - (krand() & 1023); + + scount--; + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void shootrpg(int i, int p, int sx, int sy, int sz, int sa, int atwith) +{ + spritetype* const s = &sprite[i]; + int sect = s->sectnum; + int vel, zvel; + short l, j, scount; + + if (s->extra >= 0) s->shade = -96; + + scount = 1; + vel = 644; + + j = -1; + + if (p >= 0) + { + j = aim(s, 48); + if (j >= 0) + { + int dal = ((sprite[j].xrepeat * tilesiz[sprite[j].picnum].y) << 1) + (8 << 8); + zvel = ((sprite[j].z - sz - dal) * vel) / ldist(&sprite[ps[p].i], &sprite[j]); + if (sprite[j].picnum != RECON) + sa = getangle(sprite[j].x - sx, sprite[j].y - sy); + } + else zvel = -mulscale16(ps[p].horizon.sum().asq16(), 81); + if (atwith == RPG) + S_PlayActorSound(RPG_SHOOT, i); + + } + else + { + int x; + j = findplayer(s, &x); + sa = getangle(ps[j].oposx - sx, ps[j].oposy - sy); + if (s->picnum == BOSS3) + { + int zoffs = (32 << 8); + if (isWorldTour()) // Twentieth Anniversary World Tour + zoffs = (int)((sprite[i].yrepeat / 80.0f) * zoffs); + sz -= zoffs; + } + else if (s->picnum == BOSS2) + { + vel += 128; + int zoffs = 24 << 8; + if (isWorldTour()) // Twentieth Anniversary World Tour + zoffs = (int)((sprite[i].yrepeat / 80.0f) * zoffs); + sz += zoffs; + } + + l = ldist(&sprite[ps[j].i], s); + zvel = ((ps[j].oposz - sz) * vel) / l; + + if (badguy(s) && (s->hitag & face_player_smart)) + sa = s->ang + (krand() & 31) - 16; + } + + if (p >= 0 && j >= 0) + l = j; + else l = -1; + + j = EGS(sect, + sx + (sintable[(348 + sa + 512) & 2047] / 448), + sy + (sintable[(sa + 348) & 2047] / 448), + sz - (1 << 8), atwith, 0, 14, 14, sa, vel, zvel, i, 4); + + sprite[j].extra += (krand() & 7); + if (atwith != FREEZEBLAST) + sprite[j].yvel = l; + else + { + sprite[j].yvel = numfreezebounces; + sprite[j].xrepeat >>= 1; + sprite[j].yrepeat >>= 1; + sprite[j].zvel -= (2 << 4); + } + + if (p == -1) + { + if (s->picnum == BOSS3) + { + int xoffs = sintable[sa & 2047] >> 6; + int yoffs = sintable[(sa + 1024 + 512) & 2047] >> 6; + int aoffs = 4; + + if ((krand() & 1) != 0) + { + xoffs = -xoffs; + yoffs = -yoffs; + aoffs = -8; + } + + if (isWorldTour()) // Twentieth Anniversary World Tour + { + float siz = sprite[i].yrepeat / 80.0f; + xoffs *= siz; + yoffs *= siz; + aoffs *= siz; + } + + sprite[j].x += xoffs; + sprite[j].y += yoffs; + sprite[j].ang += aoffs; + + sprite[j].xrepeat = 42; + sprite[j].yrepeat = 42; + } + else if (s->picnum == BOSS2) + { + int xoffs = sintable[sa & 2047] / 56; + int yoffs = sintable[(sa + 1024 + 512) & 2047] / 56; + int aoffs = 8 + (krand() & 255) - 128; + + if (isWorldTour()) { // Twentieth Anniversary World Tour + int siz = sprite[i].yrepeat; + xoffs = Scale(xoffs, siz, 80); + yoffs = Scale(yoffs, siz, 80); + aoffs = Scale(aoffs, siz, 80); + } + + sprite[j].x -= xoffs; + sprite[j].y -= yoffs; + sprite[j].ang -= aoffs; + + sprite[j].x -= sintable[sa & 2047] / 56; + sprite[j].y -= sintable[(sa + 1024 + 512) & 2047] / 56; + sprite[j].ang -= 8 + (krand() & 255) - 128; + sprite[j].xrepeat = 24; + sprite[j].yrepeat = 24; + + + } + else if (atwith != FREEZEBLAST) + { + sprite[j].xrepeat = 30; + sprite[j].yrepeat = 30; + sprite[j].extra >>= 2; + } + } + else if ((isWW2GI() && aplWeaponWorksLike[ps[p].curr_weapon][p] == DEVISTATOR_WEAPON) || (!isWW2GI() && ps[p].curr_weapon == DEVISTATOR_WEAPON)) + { + sprite[j].extra >>= 2; + sprite[j].ang += 16 - (krand() & 31); + sprite[j].zvel += 256 - (krand() & 511); + + if (ps[p].hbomb_hold_delay) + { + sprite[j].x -= sintable[sa & 2047] / 644; + sprite[j].y -= sintable[(sa + 1024 + 512) & 2047] / 644; + } + else + { + sprite[j].x += sintable[sa & 2047] >> 8; + sprite[j].y += sintable[(sa + 1024 + 512) & 2047] >> 8; + } + sprite[j].xrepeat >>= 1; + sprite[j].yrepeat >>= 1; + } + + sprite[j].cstat = 128; + if (atwith == RPG) + sprite[j].clipdist = 4; + else + sprite[j].clipdist = 40; + +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void shootlaser(int i, int p, int sx, int sy, int sz, int sa) +{ + spritetype* const s = &sprite[i]; + int sect = s->sectnum; + int zvel; + short hitsect, hitspr, hitwall, j, k; + int hitx, hity, hitz; + + if (p >= 0) + zvel = -ps[p].horizon.sum().asq16() >> 11; + else zvel = 0; + + hitscan(sx, sy, sz - ps[p].pyoff, sect, + sintable[(sa + 512) & 2047], + sintable[sa & 2047], + zvel << 6, &hitsect, &hitwall, &hitspr, &hitx, &hity, &hitz, CLIPMASK1); + + j = 0; + if (hitspr >= 0) return; + + if (hitwall >= 0 && hitsect >= 0) + if (((hitx - sx) * (hitx - sx) + (hity - sy) * (hity - sy)) < (290 * 290)) + { + if (wall[hitwall].nextsector >= 0) + { + if (sector[wall[hitwall].nextsector].lotag <= 2 && sector[hitsect].lotag <= 2) + j = 1; + } + else if (sector[hitsect].lotag <= 2) + j = 1; + } + + if (j == 1) + { + k = EGS(hitsect, hitx, hity, hitz, TRIPBOMB, -16, 4, 5, sa, 0, 0, i, 6); + if (isWW2GI()) + { + int lTripBombControl = GetGameVar("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, -1, -1); + if (lTripBombControl & TRIPBOMB_TIMER) + { + int lLifetime = GetGameVar("STICKYBOMB_LIFETIME", NAM_GRENADE_LIFETIME, -1, p); + int lLifetimeVar = GetGameVar("STICKYBOMB_LIFETIME_VAR", NAM_GRENADE_LIFETIME_VAR, -1, p); + // set timer. blows up when at zero.... + sprite[k].extra = lLifetime + + mulscale(krand(), lLifetimeVar, 14) + - lLifetimeVar; + } + } + + sprite[k].hitag = k; + S_PlayActorSound(LASERTRIP_ONWALL, k); + sprite[k].xvel = -20; + ssp(k, CLIPMASK0); + sprite[k].cstat = 16; + hittype[k].temp_data[5] = sprite[k].ang = getangle(wall[hitwall].x - wall[wall[hitwall].point2].x, wall[hitwall].y - wall[wall[hitwall].point2].y) - 512; + + if (p >= 0) + ps[p].ammo_amount[TRIPBOMB_WEAPON]--; + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void shootgrowspark(int i, int p, int sx, int sy, int sz, int sa) +{ + spritetype* const s = &sprite[i]; + int sect = s->sectnum; + int zvel; + short hitsect, hitspr, hitwall, j, k; + int hitx, hity, hitz; + + if (p >= 0) + { + j = aim(s, AUTO_AIM_ANGLE); + if (j >= 0) + { + int dal = ((sprite[j].xrepeat * tilesiz[sprite[j].picnum].y) << 1) + (5 << 8); + switch (sprite[j].picnum) + { + case GREENSLIME: + case GREENSLIME + 1: + case GREENSLIME + 2: + case GREENSLIME + 3: + case GREENSLIME + 4: + case GREENSLIME + 5: + case GREENSLIME + 6: + case GREENSLIME + 7: + case ROTATEGUN: + dal -= (8 << 8); + break; + } + zvel = ((sprite[j].z - sz - dal) << 8) / (ldist(&sprite[ps[p].i], &sprite[j])); + sa = getangle(sprite[j].x - sx, sprite[j].y - sy); + } + else + { + sa += 16 - (krand() & 31); + zvel = -ps[p].horizon.sum().asq16() >> 11; + zvel += 128 - (krand() & 255); + } + + sz -= (2 << 8); + } + else + { + int x; + j = findplayer(s, &x); + sz -= (4 << 8); + zvel = ((ps[j].posz - sz) << 8) / (ldist(&sprite[ps[j].i], s)); + zvel += 128 - (krand() & 255); + sa += 32 - (krand() & 63); + } + + k = 0; + + // RESHOOTGROW: + + s->cstat &= ~257; + hitscan(sx, sy, sz, sect, + sintable[(sa + 512) & 2047], + sintable[sa & 2047], + zvel << 6, &hitsect, &hitwall, &hitspr, &hitx, &hity, &hitz, CLIPMASK1); + + s->cstat |= 257; + + j = EGS(sect, hitx, hity, hitz, GROWSPARK, -16, 28, 28, sa, 0, 0, i, 1); + + sprite[j].pal = 2; + sprite[j].cstat |= 130; + sprite[j].xrepeat = sprite[j].yrepeat = 1; + + if (hitwall == -1 && hitspr == -1 && hitsect >= 0) + { + if (zvel < 0 && (sector[hitsect].ceilingstat & 1) == 0) + fi.checkhitceiling(hitsect); + } + else if (hitspr >= 0) fi.checkhitsprite(hitspr, j); + else if (hitwall >= 0 && wall[hitwall].picnum != ACCESSSWITCH && wall[hitwall].picnum != ACCESSSWITCH2) + { + fi.checkhitwall(j, hitwall, hitx, hity, hitz, GROWSPARK); + } +} + //--------------------------------------------------------------------------- // // @@ -88,9 +1062,8 @@ void incur_damage_d(struct player_struct* p) void shoot_d(int i, int atwith) { - short sect, hitsect, hitspr, hitwall, l, sa, p, j, k, scount; - int sx, sy, sz, vel, zvel, hitx, hity, hitz, x, oldzvel, dal; - unsigned char sizx, sizy; + short sect, l, j, k; + int sx, sy, sz, sa, p, vel, zvel, x, dal; spritetype* const s = &sprite[i]; if (s->picnum == TILE_APLAYER) { @@ -145,124 +1118,13 @@ void shoot_d(int i, int atwith) switch (atwith) { case FIREBALL: - { - if (s->extra >= 0) - s->shade = -96; - - sz -= (4 << 7); - if (sprite[i].picnum != BOSS5) - vel = 840; - else { - vel = 968; - sz += 6144; - } - - if (p < 0) - { - sa += 16 - (krand() & 31); - int scratch; - j = findplayer(s, &scratch); - zvel = (((ps[j].oposz - sz + (3 << 8))) * vel) / ldist(&sprite[ps[j].i], s); - } - else - { - zvel = -mulscale16(ps[p].horizon.sum().asq16(), 98); - sx += sintable[(sa + 860) & 0x7FF] / 448; - sy += sintable[(sa + 348) & 0x7FF] / 448; - sz += (3 << 8); - } - - sizx = 18; - sizy = 18; - if (p >= 0) - { - sizx = 7; - sizy = 7; - } - - j = EGS(sect, sx, sy, sz, atwith, -127, sizx, sizy, sa, vel, zvel, i, (short)4); - auto spr = &sprite[j]; - spr->extra += (krand() & 7); - if (sprite[i].picnum == BOSS5 || p >= 0) - { - spr->xrepeat = 40; - spr->yrepeat = 40; - } - spr->yvel = p; - spr->cstat = 128; - spr->clipdist = 4; + shootfireball(i, p, sx, sy, sz, sa); return; - } + case FLAMETHROWERFLAME: - if (s->extra >= 0) - s->shade = -96; - vel = 400; - - k = -1; - if (p < 0) - { - j = findplayer(s, &x); - sa = getangle(ps[j].oposx - sx, ps[j].oposy - sy); - - if (sprite[i].picnum == BOSS5) - { - vel = 528; - sz += 6144; - } - else if (sprite[i].picnum == BOSS3) - sz -= 8192; - - l = ldist(&sprite[ps[j].i], s); - if (l != 0) - zvel = ((ps[j].oposz - sz) * vel) / l; - - if (badguy(s) && (s->hitag & face_player_smart) != 0) - sa = (short)(s->ang + (krand() & 31) - 16); - - if (sector[s->sectnum].lotag == 2 && (krand() % 5) == 0) - k = fi.spawn(i, WATERBUBBLE); - } - else - { - zvel = -mulscale16(ps[p].horizon.sum().asq16(), 81); - if (sprite[ps[p].i].xvel != 0) - vel = (int)((((512 - (1024 - - abs(abs(getangle(sx - ps[p].oposx, sy - ps[p].oposy) - sa) - 1024))) - * 0.001953125f) * sprite[ps[p].i].xvel) + 400); - if (sector[s->sectnum].lotag == 2 && (krand() % 5) == 0) - k = fi.spawn(i, WATERBUBBLE); - } - - if (k == -1) - { - k = fi.spawn(i, atwith); - sprite[k].xvel = (short)vel; - sprite[k].zvel = (short)zvel; - } - - sprite[k].x = sx + sintable[(sa + 630) & 0x7FF] / 448; - sprite[k].y = sy + sintable[(sa + 112) & 0x7FF] / 448; - sprite[k].z = sz - 256; - sprite[k].sectnum = sect; - sprite[k].cstat = 0x80; - sprite[k].ang = sa; - sprite[k].xrepeat = 2; - sprite[k].yrepeat = 2; - sprite[k].clipdist = 40; - sprite[k].yvel = p; - sprite[k].owner = (short)i; - - if (p == -1) - { - if (sprite[i].picnum == BOSS5) - { - sprite[k].x -= sintable[sa & 2047] / 56; - sprite[k].y -= sintable[(sa + 1024 + 512) & 2047] / 56; - sprite[k].xrepeat = 10; - sprite[k].yrepeat = 10; - } - } + shootflamethrowerflame(i, p, sx, sy, sz, sa); return; + case FIREFLY: // BOSS5 shot k = fi.spawn(i, atwith); sprite[k].sectnum = sect; @@ -282,686 +1144,34 @@ void shoot_d(int i, int atwith) case BLOODSPLAT2: case BLOODSPLAT3: case BLOODSPLAT4: + shootbloodsplat(i, p, sx, sy, sz, sa, atwith); + break; - if (p >= 0) - sa += 64 - (krand() & 127); - else sa += 1024 + 64 - (krand() & 127); - zvel = 1024 - (krand() & 2047); case KNEE: - if (atwith == KNEE) - { - if (p >= 0) - { - zvel = -ps[p].horizon.sum().asq16() >> 11; - sz += (6 << 8); - sa += 15; - } - else - { - j = ps[findplayer(s, &x)].i; - zvel = ((sprite[j].z - sz) << 8) / (x + 1); - sa = getangle(sprite[j].x - sx, sprite[j].y - sy); - } - } - - // writestring(sx,sy,sz,sect,sintable[(sa+512)&2047],sintable[sa&2047],zvel<<6); - - hitscan(sx, sy, sz, sect, - sintable[(sa + 512) & 2047], - sintable[sa & 2047], zvel << 6, - &hitsect, &hitwall, &hitspr, &hitx, &hity, &hitz, CLIPMASK1); - - if (atwith == BLOODSPLAT1 || - atwith == BLOODSPLAT2 || - atwith == BLOODSPLAT3 || - atwith == BLOODSPLAT4) - { - if (FindDistance2D(sx - hitx, sy - hity) < 1024) - if (hitwall >= 0 && wall[hitwall].overpicnum != BIGFORCE) - if ((wall[hitwall].nextsector >= 0 && hitsect >= 0 && - sector[wall[hitwall].nextsector].lotag == 0 && - sector[hitsect].lotag == 0 && - sector[wall[hitwall].nextsector].lotag == 0 && - (sector[hitsect].floorz - sector[wall[hitwall].nextsector].floorz) > (16 << 8)) || - (wall[hitwall].nextsector == -1 && sector[hitsect].lotag == 0)) - if ((wall[hitwall].cstat & 16) == 0) - { - if (wall[hitwall].nextsector >= 0) - { - SectIterator it(wall[hitwall].nextsector); - while ((k = it.NextIndex()) >= 0) - { - if (sprite[k].statnum == 3 && sprite[k].lotag == 13) - return; - } - } - - if (wall[hitwall].nextwall >= 0 && - wall[wall[hitwall].nextwall].hitag != 0) - return; - - if (wall[hitwall].hitag == 0) - { - k = fi.spawn(i, atwith); - sprite[k].xvel = -12; - sprite[k].ang = getangle(wall[hitwall].x - wall[wall[hitwall].point2].x, - wall[hitwall].y - wall[wall[hitwall].point2].y) + 512; - sprite[k].x = hitx; - sprite[k].y = hity; - sprite[k].z = hitz; - sprite[k].cstat |= (krand() & 4); - ssp(k, CLIPMASK0); - setsprite(k, sprite[k].x, sprite[k].y, sprite[k].z); - if (s->picnum == OOZFILTER || s->picnum == NEWBEAST) - sprite[k].pal = 6; - } - } - return; - } - - if (hitsect < 0) break; - - if ((abs(sx - hitx) + abs(sy - hity)) < 1024) - { - if (hitwall >= 0 || hitspr >= 0) - { - j = EGS(hitsect, hitx, hity, hitz, KNEE, -15, 0, 0, sa, 32, 0, i, 4); - sprite[j].extra += (krand() & 7); - if (p >= 0) - { - k = fi.spawn(j, SMALLSMOKE); - sprite[k].z -= (8 << 8); - S_PlayActorSound(KICK_HIT, j); - } - - if (p >= 0 && ps[p].steroids_amount > 0 && ps[p].steroids_amount < 400) - sprite[j].extra += (max_player_health >> 2); - - if (hitspr >= 0 && sprite[hitspr].picnum != ACCESSSWITCH && sprite[hitspr].picnum != ACCESSSWITCH2) - { - fi.checkhitsprite(hitspr, j); - if (p >= 0) fi.checkhitswitch(p, hitspr, 1); - } - - else if (hitwall >= 0) - { - if (wall[hitwall].cstat & 2) - if (wall[hitwall].nextsector >= 0) - if (hitz >= (sector[wall[hitwall].nextsector].floorz)) - hitwall = wall[hitwall].nextwall; - - if (hitwall >= 0 && wall[hitwall].picnum != ACCESSSWITCH && wall[hitwall].picnum != ACCESSSWITCH2) - { - fi.checkhitwall(j, hitwall, hitx, hity, hitz, atwith); - if (p >= 0) fi.checkhitswitch(p, hitwall, 0); - } - } - } - else if (p >= 0 && zvel > 0 && sector[hitsect].lotag == 1) - { - j = fi.spawn(ps[p].i, WATERSPLASH2); - sprite[j].x = hitx; - sprite[j].y = hity; - sprite[j].ang = ps[p].angle.ang.asbuild(); // Total tweek - sprite[j].xvel = 32; - ssp(i, CLIPMASK0); - sprite[j].xvel = 0; - - } - } - + shootknee(i, p, sx, sy, sz, sa); break; case SHOTSPARK1: case SHOTGUN: case CHAINGUN: - - if (s->extra >= 0) s->shade = -96; - - if (p >= 0) - { - SetGameVarID(g_iAimAngleVarID, AUTO_AIM_ANGLE, i, p); - OnEvent(EVENT_GETAUTOAIMANGLE, i, p, -1); - j = -1; - if (GetGameVarID(g_iAimAngleVarID, i, p) > 0) - { - j = aim(s, GetGameVarID(g_iAimAngleVarID, i, p)); - } - - if (j >= 0) - { - dal = ((sprite[j].xrepeat * tilesiz[sprite[j].picnum].y) << 1) + (5 << 8); - switch (sprite[j].picnum) - { - case GREENSLIME: - case GREENSLIME + 1: - case GREENSLIME + 2: - case GREENSLIME + 3: - case GREENSLIME + 4: - case GREENSLIME + 5: - case GREENSLIME + 6: - case GREENSLIME + 7: - case ROTATEGUN: - dal -= (8 << 8); - break; - } - zvel = ((sprite[j].z - sz - dal) << 8) / ldist(&sprite[ps[p].i], &sprite[j]); - sa = getangle(sprite[j].x - sx, sprite[j].y - sy); - } - - if (isWW2GI()) - { - int angRange = 32; - int zRange = 256; - SetGameVarID(g_iAngRangeVarID, 32, i, p); - SetGameVarID(g_iZRangeVarID, 256, i, p); - OnEvent(EVENT_GETSHOTRANGE, i, p, -1); - angRange = GetGameVarID(g_iAngRangeVarID, i, p); - zRange = GetGameVarID(g_iZRangeVarID, i, p); - - sa += (angRange / 2) - (krand() & (angRange - 1)); - if (j == -1) - { - // no target - zvel = -ps[p].horizon.sum().asq16() >> 11; - } - zvel += (zRange / 2) - (krand() & (zRange - 1)); - } - else if (j == -1) - { - sa += 16 - (krand() & 31); - zvel = -ps[p].horizon.sum().asq16() >> 11; - zvel += 128 - (krand() & 255); - } - - sz -= (2 << 8); - } - else - { - j = findplayer(s, &x); - sz -= (4 << 8); - zvel = ((ps[j].posz - sz) << 8) / (ldist(&sprite[ps[j].i], s)); - if (s->picnum != BOSS1) - { - zvel += 128 - (krand() & 255); - sa += 32 - (krand() & 63); - } - else - { - zvel += 128 - (krand() & 255); - sa = getangle(ps[j].posx - sx, ps[j].posy - sy) + 64 - (krand() & 127); - } - } - - s->cstat &= ~257; - hitscan(sx, sy, sz, sect, - sintable[(sa + 512) & 2047], - sintable[sa & 2047], - zvel << 6, &hitsect, &hitwall, &hitspr, &hitx, &hity, &hitz, CLIPMASK1); - s->cstat |= 257; - - if (hitsect < 0) return; - - if ((krand() & 15) == 0 && sector[hitsect].lotag == 2) - tracers(hitx, hity, hitz, sx, sy, sz, 8 - (ud.multimode >> 1)); - - if (p >= 0) - { - k = EGS(hitsect, hitx, hity, hitz, SHOTSPARK1, -15, 10, 10, sa, 0, 0, i, 4); - sprite[k].extra = ScriptCode[actorinfo[atwith].scriptaddress]; - sprite[k].extra += (krand() % 6); - - if (hitwall == -1 && hitspr == -1) - { - if (zvel < 0) - { - if (sector[hitsect].ceilingstat & 1) - { - sprite[k].xrepeat = 0; - sprite[k].yrepeat = 0; - return; - } - else - fi.checkhitceiling(hitsect); - } - fi.spawn(k, SMALLSMOKE); - } - - if (hitspr >= 0) - { - fi.checkhitsprite(hitspr, k); - if (sprite[hitspr].picnum == TILE_APLAYER && (ud.coop != 1 || ud.ffire == 1)) - { - l = fi.spawn(k, JIBS6); - sprite[k].xrepeat = sprite[k].yrepeat = 0; - sprite[l].z += (4 << 8); - sprite[l].xvel = 16; - sprite[l].xrepeat = sprite[l].yrepeat = 24; - sprite[l].ang += 64 - (krand() & 127); - } - else fi.spawn(k, SMALLSMOKE); - - if (p >= 0 && ( - sprite[hitspr].picnum == DIPSWITCH || - sprite[hitspr].picnum == DIPSWITCH + 1 || - sprite[hitspr].picnum == DIPSWITCH2 || - sprite[hitspr].picnum == DIPSWITCH2 + 1 || - sprite[hitspr].picnum == DIPSWITCH3 || - sprite[hitspr].picnum == DIPSWITCH3 + 1 || - sprite[hitspr].picnum == HANDSWITCH || - sprite[hitspr].picnum == HANDSWITCH + 1)) - { - fi.checkhitswitch(p, hitspr, 1); - return; - } - } - else if (hitwall >= 0) - { - fi.spawn(k, SMALLSMOKE); - - if (fi.isadoorwall(wall[hitwall].picnum) == 1) - goto SKIPBULLETHOLE; - if (p >= 0 && ( - wall[hitwall].picnum == DIPSWITCH || - wall[hitwall].picnum == DIPSWITCH + 1 || - wall[hitwall].picnum == DIPSWITCH2 || - wall[hitwall].picnum == DIPSWITCH2 + 1 || - wall[hitwall].picnum == DIPSWITCH3 || - wall[hitwall].picnum == DIPSWITCH3 + 1 || - wall[hitwall].picnum == HANDSWITCH || - wall[hitwall].picnum == HANDSWITCH + 1)) - { - fi.checkhitswitch(p, hitwall, 0); - return; - } - - if (wall[hitwall].hitag != 0 || (wall[hitwall].nextwall >= 0 && wall[wall[hitwall].nextwall].hitag != 0)) - goto SKIPBULLETHOLE; - - if (hitsect >= 0 && sector[hitsect].lotag == 0) - if (wall[hitwall].overpicnum != BIGFORCE) - if ((wall[hitwall].nextsector >= 0 && sector[wall[hitwall].nextsector].lotag == 0) || - (wall[hitwall].nextsector == -1 && sector[hitsect].lotag == 0)) - if ((wall[hitwall].cstat & 16) == 0) - { - if (wall[hitwall].nextsector >= 0) - { - SectIterator it(wall[hitwall].nextsector); - while ((l = it.NextIndex()) >= 0) - { - if (sprite[l].statnum == 3 && sprite[l].lotag == 13) - goto SKIPBULLETHOLE; - } - } - - StatIterator it(STAT_MISC); - while ((l = it.NextIndex()) >= 0) - { - if (sprite[l].picnum == BULLETHOLE) - if (dist(&sprite[l], &sprite[k]) < (12 + (krand() & 7))) - goto SKIPBULLETHOLE; - } - l = fi.spawn(k, BULLETHOLE); - sprite[l].xvel = -1; - sprite[l].ang = getangle(wall[hitwall].x - wall[wall[hitwall].point2].x, - wall[hitwall].y - wall[wall[hitwall].point2].y) + 512; - ssp(l, CLIPMASK0); - } - - SKIPBULLETHOLE: - - if (wall[hitwall].cstat & 2) - if (wall[hitwall].nextsector >= 0) - if (hitz >= (sector[wall[hitwall].nextsector].floorz)) - hitwall = wall[hitwall].nextwall; - - fi.checkhitwall(k, hitwall, hitx, hity, hitz, SHOTSPARK1); - } - } - else - { - k = EGS(hitsect, hitx, hity, hitz, SHOTSPARK1, -15, 24, 24, sa, 0, 0, i, 4); - sprite[k].extra = ScriptCode[actorinfo[atwith].scriptaddress]; - - if (hitspr >= 0) - { - fi.checkhitsprite(hitspr, k); - if (sprite[hitspr].picnum != TILE_APLAYER) - fi.spawn(k, SMALLSMOKE); - else sprite[k].xrepeat = sprite[k].yrepeat = 0; - } - else if (hitwall >= 0) { - - fi.checkhitwall(k, hitwall, hitx, hity, hitz, SHOTSPARK1); - } - } - - if ((krand() & 255) < 4) - { - vec3_t v{ hitx, hity, hitz }; - S_PlaySound3D(PISTOL_RICOCHET, k, &v); - } - + shootweapon(i, p, sx, sy, sz, sa, atwith); return; case FIRELASER: case SPIT: case COOLEXPLOSION1: - - if (s->extra >= 0) s->shade = -96; - - scount = 1; - if (atwith == SPIT) vel = 292; - else - { - if (atwith == COOLEXPLOSION1) - { - if (s->picnum == BOSS2) vel = 644; - else vel = 348; - sz -= (4 << 7); - } - else - { - vel = 840; - sz -= (4 << 7); - } - } - - if (p >= 0) - { - j = aim(s, AUTO_AIM_ANGLE); - - if (j >= 0) - { - dal = ((sprite[j].xrepeat * tilesiz[sprite[j].picnum].y) << 1) - (12 << 8); - zvel = ((sprite[j].z - sz - dal) * vel) / ldist(&sprite[ps[p].i], &sprite[j]); - sa = getangle(sprite[j].x - sx, sprite[j].y - sy); - } - else - zvel = -mulscale16(ps[p].horizon.sum().asq16(), 98); - } - else - { - j = findplayer(s, &x); - // sa = getangle(ps[j].oposx-sx,ps[j].oposy-sy); - sa += 16 - (krand() & 31); - zvel = (((ps[j].oposz - sz + (3 << 8))) * vel) / ldist(&sprite[ps[j].i], s); - } - - oldzvel = zvel; - - if (atwith == SPIT) { sizx = 18; sizy = 18, sz -= (10 << 8); } - else - { - if (atwith == FIRELASER) - { - if (p >= 0) - { - - sizx = 34; - sizy = 34; - } - else - { - sizx = 18; - sizy = 18; - } - } - else - { - sizx = 18; - sizy = 18; - } - } - - if (p >= 0) sizx = 7, sizy = 7; - - while (scount > 0) - { - j = EGS(sect, sx, sy, sz, atwith, -127, sizx, sizy, sa, vel, zvel, i, 4); - sprite[j].extra += (krand() & 7); - - if (atwith == COOLEXPLOSION1) - { - sprite[j].shade = 0; - if (s->picnum == BOSS2) - { - l = sprite[j].xvel; - sprite[j].xvel = 1024; - ssp(j, CLIPMASK0); - sprite[j].xvel = l; - sprite[j].ang += 128 - (krand() & 255); - } - } - - sprite[j].cstat = 128; - sprite[j].clipdist = 4; - - sa = s->ang + 32 - (krand() & 63); - zvel = oldzvel + 512 - (krand() & 1023); - - scount--; - } - + shootstuff(i, p, sx, sy, sz, sa, atwith); return; case FREEZEBLAST: sz += (3 << 8); case RPG: - if (s->extra >= 0) s->shade = -96; - - scount = 1; - vel = 644; - - j = -1; - - if (p >= 0) - { - j = aim(s, 48); - if (j >= 0) - { - dal = ((sprite[j].xrepeat * tilesiz[sprite[j].picnum].y) << 1) + (8 << 8); - zvel = ((sprite[j].z - sz - dal) * vel) / ldist(&sprite[ps[p].i], &sprite[j]); - if (sprite[j].picnum != RECON) - sa = getangle(sprite[j].x - sx, sprite[j].y - sy); - } - else zvel = -mulscale16(ps[p].horizon.sum().asq16(), 81); - if (atwith == RPG) - S_PlayActorSound(RPG_SHOOT, i); - - } - else - { - j = findplayer(s, &x); - sa = getangle(ps[j].oposx - sx, ps[j].oposy - sy); - if (s->picnum == BOSS3) - { - int zoffs = (32 << 8); - if (isWorldTour()) // Twentieth Anniversary World Tour - zoffs = (int)((sprite[i].yrepeat / 80.0f) * zoffs); - sz -= zoffs; - } - else if (s->picnum == BOSS2) - { - vel += 128; - int zoffs = 24 << 8; - if (isWorldTour()) // Twentieth Anniversary World Tour - zoffs = (int)((sprite[i].yrepeat / 80.0f) * zoffs); - sz += zoffs; - } - - l = ldist(&sprite[ps[j].i], s); - zvel = ((ps[j].oposz - sz) * vel) / l; - - if (badguy(s) && (s->hitag & face_player_smart)) - sa = s->ang + (krand() & 31) - 16; - } - - if (p >= 0 && j >= 0) - l = j; - else l = -1; - - j = EGS(sect, - sx + (sintable[(348 + sa + 512) & 2047] / 448), - sy + (sintable[(sa + 348) & 2047] / 448), - sz - (1 << 8), atwith, 0, 14, 14, sa, vel, zvel, i, 4); - - sprite[j].extra += (krand() & 7); - if (atwith != FREEZEBLAST) - sprite[j].yvel = l; - else - { - sprite[j].yvel = numfreezebounces; - sprite[j].xrepeat >>= 1; - sprite[j].yrepeat >>= 1; - sprite[j].zvel -= (2 << 4); - } - - if (p == -1) - { - if (s->picnum == BOSS3) - { - int xoffs = sintable[sa & 2047] >> 6; - int yoffs = sintable[(sa + 1024 + 512) & 2047] >> 6; - int aoffs = 4; - - if ((krand() & 1) != 0) - { - xoffs = -xoffs; - yoffs = -yoffs; - aoffs = -8; - } - - if (isWorldTour()) // Twentieth Anniversary World Tour - { - float siz = sprite[i].yrepeat / 80.0f; - xoffs *= siz; - yoffs *= siz; - aoffs *= siz; - } - - sprite[j].x += xoffs; - sprite[j].y += yoffs; - sprite[j].ang += aoffs; - - sprite[j].xrepeat = 42; - sprite[j].yrepeat = 42; - } - else if (s->picnum == BOSS2) - { - int xoffs = sintable[sa & 2047] / 56; - int yoffs = sintable[(sa + 1024 + 512) & 2047] / 56; - int aoffs = 8 + (krand() & 255) - 128; - - if (isWorldTour()) { // Twentieth Anniversary World Tour - int siz = sprite[i].yrepeat; - xoffs = Scale(xoffs, siz, 80); - yoffs = Scale(yoffs, siz, 80); - aoffs = Scale(aoffs, siz, 80); - } - - sprite[j].x -= xoffs; - sprite[j].y -= yoffs; - sprite[j].ang -= aoffs; - - sprite[j].x -= sintable[sa & 2047] / 56; - sprite[j].y -= sintable[(sa + 1024 + 512) & 2047] / 56; - sprite[j].ang -= 8 + (krand() & 255) - 128; - sprite[j].xrepeat = 24; - sprite[j].yrepeat = 24; - - - } - else if (atwith != FREEZEBLAST) - { - sprite[j].xrepeat = 30; - sprite[j].yrepeat = 30; - sprite[j].extra >>= 2; - } - } - else if ((isWW2GI() && aplWeaponWorksLike[ps[p].curr_weapon][p] == DEVISTATOR_WEAPON) || (!isWW2GI() && ps[p].curr_weapon == DEVISTATOR_WEAPON)) - { - sprite[j].extra >>= 2; - sprite[j].ang += 16 - (krand() & 31); - sprite[j].zvel += 256 - (krand() & 511); - - if (ps[p].hbomb_hold_delay) - { - sprite[j].x -= sintable[sa & 2047] / 644; - sprite[j].y -= sintable[(sa + 1024 + 512) & 2047] / 644; - } - else - { - sprite[j].x += sintable[sa & 2047] >> 8; - sprite[j].y += sintable[(sa + 1024 + 512) & 2047] >> 8; - } - sprite[j].xrepeat >>= 1; - sprite[j].yrepeat >>= 1; - } - - sprite[j].cstat = 128; - if (atwith == RPG) - sprite[j].clipdist = 4; - else - sprite[j].clipdist = 40; - + shootrpg(i, p, sx, sy, sz, sa, atwith); break; case HANDHOLDINGLASER: - - if (p >= 0) - zvel = -ps[p].horizon.sum().asq16() >> 11; - else zvel = 0; - - hitscan(sx, sy, sz - ps[p].pyoff, sect, - sintable[(sa + 512) & 2047], - sintable[sa & 2047], - zvel << 6, &hitsect, &hitwall, &hitspr, &hitx, &hity, &hitz, CLIPMASK1); - - j = 0; - if (hitspr >= 0) break; - - if (hitwall >= 0 && hitsect >= 0) - if (((hitx - sx) * (hitx - sx) + (hity - sy) * (hity - sy)) < (290 * 290)) - { - if (wall[hitwall].nextsector >= 0) - { - if (sector[wall[hitwall].nextsector].lotag <= 2 && sector[hitsect].lotag <= 2) - j = 1; - } - else if (sector[hitsect].lotag <= 2) - j = 1; - } - - if (j == 1) - { - k = EGS(hitsect, hitx, hity, hitz, TRIPBOMB, -16, 4, 5, sa, 0, 0, i, 6); - if (isWW2GI()) - { - int lTripBombControl = GetGameVar("TRIPBOMB_CONTROL", TRIPBOMB_TRIPWIRE, -1, -1); - if (lTripBombControl & TRIPBOMB_TIMER) - { - int lLifetime = GetGameVar("STICKYBOMB_LIFETIME", NAM_GRENADE_LIFETIME, -1, p); - int lLifetimeVar = GetGameVar("STICKYBOMB_LIFETIME_VAR", NAM_GRENADE_LIFETIME_VAR, -1, p); - // set timer. blows up when at zero.... - sprite[k].extra = lLifetime - + mulscale(krand(), lLifetimeVar, 14) - - lLifetimeVar; - } - } - - sprite[k].hitag = k; - S_PlayActorSound(LASERTRIP_ONWALL, k); - sprite[k].xvel = -20; - ssp(k, CLIPMASK0); - sprite[k].cstat = 16; - hittype[k].temp_data[5] = sprite[k].ang = getangle(wall[hitwall].x - wall[wall[hitwall].point2].x, wall[hitwall].y - wall[wall[hitwall].point2].y) - 512; - - if (p >= 0) - ps[p].ammo_amount[TRIPBOMB_WEAPON]--; - - } + shootlaser(i, p, sx, sy, sz, sa); return; case BOUNCEMINE: @@ -985,95 +1195,7 @@ void shoot_d(int i, int atwith) break; case GROWSPARK: - - if (p >= 0) - { - j = aim(s, AUTO_AIM_ANGLE); - if (j >= 0) - { - dal = ((sprite[j].xrepeat * tilesiz[sprite[j].picnum].y) << 1) + (5 << 8); - switch (sprite[j].picnum) - { - case GREENSLIME: - case GREENSLIME + 1: - case GREENSLIME + 2: - case GREENSLIME + 3: - case GREENSLIME + 4: - case GREENSLIME + 5: - case GREENSLIME + 6: - case GREENSLIME + 7: - case ROTATEGUN: - dal -= (8 << 8); - break; - } - zvel = ((sprite[j].z - sz - dal) << 8) / (ldist(&sprite[ps[p].i], &sprite[j])); - sa = getangle(sprite[j].x - sx, sprite[j].y - sy); - } - else - { - sa += 16 - (krand() & 31); - zvel = -ps[p].horizon.sum().asq16() >> 11; - zvel += 128 - (krand() & 255); - } - - sz -= (2 << 8); - } - else - { - j = findplayer(s, &x); - sz -= (4 << 8); - zvel = ((ps[j].posz - sz) << 8) / (ldist(&sprite[ps[j].i], s)); - zvel += 128 - (krand() & 255); - sa += 32 - (krand() & 63); - } - - k = 0; - - // RESHOOTGROW: - - s->cstat &= ~257; - hitscan(sx, sy, sz, sect, - sintable[(sa + 512) & 2047], - sintable[sa & 2047], - zvel << 6, &hitsect, &hitwall, &hitspr, &hitx, &hity, &hitz, CLIPMASK1); - - s->cstat |= 257; - - j = EGS(sect, hitx, hity, hitz, GROWSPARK, -16, 28, 28, sa, 0, 0, i, 1); - - sprite[j].pal = 2; - sprite[j].cstat |= 130; - sprite[j].xrepeat = sprite[j].yrepeat = 1; - - if (hitwall == -1 && hitspr == -1 && hitsect >= 0) - { - if (zvel < 0 && (sector[hitsect].ceilingstat & 1) == 0) - fi.checkhitceiling(hitsect); - } - else if (hitspr >= 0) fi.checkhitsprite(hitspr, j); - else if (hitwall >= 0 && wall[hitwall].picnum != ACCESSSWITCH && wall[hitwall].picnum != ACCESSSWITCH2) - { - /* if(wall[hitwall].overpicnum == MIRROR && k == 0) - { - l = getangle( - wall[wall[hitwall].point2].x-wall[hitwall].x, - wall[wall[hitwall].point2].y-wall[hitwall].y); - - sx = hitx; - sy = hity; - sz = hitz; - sect = hitsect; - sa = ((l<<1) - sa)&2047; - sx += sintable[(sa+512)&2047]>>12; - sy += sintable[sa&2047]>>12; - - k++; - goto RESHOOTGROW; - } - else */ - fi.checkhitwall(j, hitwall, hitx, hity, hitz, atwith); - } - + shootgrowspark(i, p, sx, sy, sz, sa); break; case SHRINKER: