Refactor projectiles a bit. Tested with all of the original weapons and with the weapons in the Duke 64 mod.

git-svn-id: https://svn.eduke32.com/eduke32@3992 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
terminx 2013-08-06 23:53:34 +00:00
parent 1d2a6bc9df
commit e83927c2f8
3 changed files with 641 additions and 611 deletions

View file

@ -2644,39 +2644,36 @@ static void Proj_BounceOffWall(spritetype *s, int32_t j)
s->ang = ((k<<1) - s->ang)&2047; s->ang = ((k<<1) - s->ang)&2047;
} }
ACTOR_STATIC void G_MoveWeapons(void) #define PROJ_DECAYVELOCITY s->xvel >>= 1, s->zvel >>= 1
{
int32_t i = headspritestat[STAT_PROJECTILE], j=0, k, q;
int32_t x, ll;
while (i >= 0) ACTOR_STATIC void Proj_MoveCustom(int32_t i)
{
const int32_t nexti = nextspritestat[i];
spritetype *const s = &sprite[i];
vec3_t davect;
if (s->sectnum < 0)
KILLIT(i);
Bmemcpy(&actor[i].bpos.x, s, sizeof(vec3_t));
/* Custom projectiles */
if (A_CheckSpriteFlags(i,SPRITE_PROJECTILE))
{ {
const projectile_t *const proj = &SpriteProjectile[i]; const projectile_t *const proj = &SpriteProjectile[i];
spritetype *const s = &sprite[i];
vec3_t davect;
int32_t j=0;
if (proj->pal >= 0) if (proj->pal >= 0)
s->pal = proj->pal; s->pal = proj->pal;
if (proj->workslike & PROJECTILE_KNEE) switch (proj->workslike & PROJECTILE_TYPE_MASK)
KILLIT(i);
if (proj->workslike & PROJECTILE_RPG)
{ {
// if (proj->workslike & COOLEXPLOSION1) case PROJECTILE_HITSCAN:
// if( g_sounds[WIERDSHOT_FLY].num == 0 ) if (!G_HaveActor(sprite[i].picnum))
// A_PlaySound(WIERDSHOT_FLY,i); return;
{
int32_t x, p = A_FindPlayer(s, &x);
A_Execute(i, p, x);
}
return;
case PROJECTILE_KNEE:
case PROJECTILE_BLOOD:
A_DeleteSprite(i);
return;
default:
case PROJECTILE_RPG:
Bmemcpy(&davect, s, sizeof(vec3_t)); Bmemcpy(&davect, s, sizeof(vec3_t));
if (proj->flashcolor) if (proj->flashcolor)
@ -2685,11 +2682,15 @@ ACTOR_STATIC void G_MoveWeapons(void)
if (proj->workslike & PROJECTILE_BOUNCESOFFWALLS && s->yvel < 1) if (proj->workslike & PROJECTILE_BOUNCESOFFWALLS && s->yvel < 1)
{ {
A_DoProjectileEffects(i, NULL, 1); A_DoProjectileEffects(i, NULL, 1);
KILLIT(i); A_DeleteSprite(i);
return;
} }
if (proj->workslike & PROJECTILE_COOLEXPLOSION1 && ++s->shade >= 40) if (proj->workslike & PROJECTILE_COOLEXPLOSION1 && ++s->shade >= 40)
KILLIT(i); {
A_DeleteSprite(i);
return;
}
s->zvel -= proj->drop; s->zvel -= proj->drop;
@ -2718,9 +2719,8 @@ ACTOR_STATIC void G_MoveWeapons(void)
{ {
int32_t cnt = proj->movecnt; int32_t cnt = proj->movecnt;
int32_t k = s->xvel;
k = s->xvel; int32_t ll = s->zvel;
ll = s->zvel;
if (sector[s->sectnum].lotag == ST_2_UNDERWATER) if (sector[s->sectnum].lotag == ST_2_UNDERWATER)
{ {
@ -2738,8 +2738,7 @@ ACTOR_STATIC void G_MoveWeapons(void)
tmpvect.z = ll; tmpvect.z = ll;
j = A_MoveSprite(i, &tmpvect, CLIPMASK1); j = A_MoveSprite(i, &tmpvect, CLIPMASK1);
} } while (!j && --cnt > 0);
while (!j && --cnt > 0);
} }
if (!(proj->workslike & PROJECTILE_BOUNCESOFFWALLS) && if (!(proj->workslike & PROJECTILE_BOUNCESOFFWALLS) &&
@ -2750,7 +2749,10 @@ ACTOR_STATIC void G_MoveWeapons(void)
actor[i].movflag = j; actor[i].movflag = j;
if (s->sectnum < 0) if (s->sectnum < 0)
KILLIT(i); {
A_DeleteSprite(i);
return;
}
if (proj->workslike & PROJECTILE_TIMED && proj->range > 0) if (proj->workslike & PROJECTILE_TIMED && proj->range > 0)
{ {
@ -2759,7 +2761,8 @@ ACTOR_STATIC void G_MoveWeapons(void)
if (proj->workslike & PROJECTILE_EXPLODEONTIMER) if (proj->workslike & PROJECTILE_EXPLODEONTIMER)
A_DoProjectileEffects(i, &davect, 1); A_DoProjectileEffects(i, &davect, 1);
KILLIT(i); A_DeleteSprite(i);
return;
} }
} }
@ -2771,14 +2774,17 @@ ACTOR_STATIC void G_MoveWeapons(void)
if (j != 0) if (j != 0)
{ {
int32_t k;
if (proj->workslike & PROJECTILE_COOLEXPLOSION1) if (proj->workslike & PROJECTILE_COOLEXPLOSION1)
{ {
s->xvel = 0; s->xvel = 0;
s->zvel = 0; s->zvel = 0;
} }
if ((j&49152) == 49152) switch (j&49152)
{ {
case 49152:
j &= (MAXSPRITES-1); j &= (MAXSPRITES-1);
if (proj->workslike & PROJECTILE_BOUNCESOFFSPRITES) if (proj->workslike & PROJECTILE_BOUNCESOFFSPRITES)
@ -2792,13 +2798,10 @@ ACTOR_STATIC void G_MoveWeapons(void)
A_PlaySound(proj->bsound, i); A_PlaySound(proj->bsound, i);
if (proj->workslike & PROJECTILE_LOSESVELOCITY) if (proj->workslike & PROJECTILE_LOSESVELOCITY)
{ PROJ_DECAYVELOCITY;
s->xvel >>= 1;
s->zvel >>= 1;
}
if (!(proj->workslike & PROJECTILE_FORCEIMPACT)) if (!(proj->workslike & PROJECTILE_FORCEIMPACT))
goto BOLT; return;
} }
A_DamageObject(j, i); A_DamageObject(j, i);
@ -2815,7 +2818,6 @@ ACTOR_STATIC void G_MoveWeapons(void)
if (proj->workslike & PROJECTILE_RPG_IMPACT) if (proj->workslike & PROJECTILE_RPG_IMPACT)
{ {
actor[j].owner = s->owner; actor[j].owner = s->owner;
actor[j].picnum = s->picnum; actor[j].picnum = s->picnum;
actor[j].extra += proj->extra; actor[j].extra += proj->extra;
@ -2823,14 +2825,17 @@ ACTOR_STATIC void G_MoveWeapons(void)
A_DoProjectileEffects(i, &davect, 0); A_DoProjectileEffects(i, &davect, 0);
if (!(proj->workslike & PROJECTILE_FORCEIMPACT)) if (!(proj->workslike & PROJECTILE_FORCEIMPACT))
KILLIT(i); {
A_DeleteSprite(i);
return;
}
} }
if (proj->workslike & PROJECTILE_FORCEIMPACT) if (proj->workslike & PROJECTILE_FORCEIMPACT)
goto BOLT; return;
} break;
else if ((j&49152) == 32768)
{ case 32768:
j &= (MAXWALLS-1); j &= (MAXWALLS-1);
if (proj->workslike & PROJECTILE_BOUNCESOFFMIRRORS && if (proj->workslike & PROJECTILE_BOUNCESOFFMIRRORS &&
@ -2839,7 +2844,7 @@ ACTOR_STATIC void G_MoveWeapons(void)
Proj_BounceOffWall(s, j); Proj_BounceOffWall(s, j);
s->owner = i; s->owner = i;
A_Spawn(i, TRANSPORTERSTAR); A_Spawn(i, TRANSPORTERSTAR);
goto BOLT; return;
} }
else else
{ {
@ -2857,22 +2862,23 @@ ACTOR_STATIC void G_MoveWeapons(void)
A_PlaySound(proj->bsound, i); A_PlaySound(proj->bsound, i);
if (proj->workslike & PROJECTILE_LOSESVELOCITY) if (proj->workslike & PROJECTILE_LOSESVELOCITY)
{ PROJ_DECAYVELOCITY;
s->xvel >>= 1;
s->zvel >>= 1; return;
}
goto BOLT;
} }
} }
} break;
else if ((j&49152) == 16384)
{ case 16384:
setsprite(i, &davect); setsprite(i, &davect);
if (s->zvel < 0) if (s->zvel < 0)
{ {
if (sector[s->sectnum].ceilingstat&1 && sector[s->sectnum].ceilingpal == 0) if (sector[s->sectnum].ceilingstat&1 && sector[s->sectnum].ceilingpal == 0)
KILLIT(i); {
A_DeleteSprite(i);
return;
}
Sect_DamageCeiling(s->sectnum); Sect_DamageCeiling(s->sectnum);
} }
@ -2888,34 +2894,41 @@ ACTOR_STATIC void G_MoveWeapons(void)
A_PlaySound(proj->bsound, i); A_PlaySound(proj->bsound, i);
if (proj->workslike & PROJECTILE_LOSESVELOCITY) if (proj->workslike & PROJECTILE_LOSESVELOCITY)
{ PROJ_DECAYVELOCITY;
s->xvel >>= 1;
s->zvel >>= 1; return;
}
break;
} }
goto BOLT;
}
}
if (proj->workslike & PROJECTILE_HITSCAN)
{
if (!G_HaveActor(sprite[i].picnum))
goto BOLT;
{
int32_t p = A_FindPlayer(s,&x);
A_Execute(i,p,x);
}
goto BOLT;
}
if (proj->workslike & PROJECTILE_RPG)
{
A_DoProjectileEffects(i, &davect, 1); A_DoProjectileEffects(i, &davect, 1);
KILLIT(i); A_DeleteSprite(i);
return;
} }
return;
} }
} }
ACTOR_STATIC void G_MoveWeapons(void)
{
int32_t i = headspritestat[STAT_PROJECTILE], j=0, k;
int32_t x, ll;
while (i >= 0)
{
const int32_t nexti = nextspritestat[i];
spritetype *const s = &sprite[i];
vec3_t davect;
if (s->sectnum < 0)
KILLIT(i);
Bmemcpy(&actor[i].bpos.x, s, sizeof(vec3_t));
/* Custom projectiles */
if (A_CheckSpriteFlags(i, SPRITE_PROJECTILE))
{
Proj_MoveCustom(i);
goto BOLT; goto BOLT;
} }
@ -2925,6 +2938,7 @@ ACTOR_STATIC void G_MoveWeapons(void)
case RADIUSEXPLOSION__STATIC: case RADIUSEXPLOSION__STATIC:
case KNEE__STATIC: case KNEE__STATIC:
KILLIT(i); KILLIT(i);
/*
case TONGUE__STATIC: case TONGUE__STATIC:
T1 = sintable[(T2)&2047]>>9; T1 = sintable[(T2)&2047]>>9;
T2 += 32; T2 += 32;
@ -2960,6 +2974,7 @@ ACTOR_STATIC void G_MoveWeapons(void)
sprite[q].picnum = INNERJAW+1; sprite[q].picnum = INNERJAW+1;
goto BOLT; goto BOLT;
*/
case FREEZEBLAST__STATIC: case FREEZEBLAST__STATIC:
if (s->yvel < 1 || s->extra < 2 || (s->xvel|s->zvel) == 0) if (s->yvel < 1 || s->extra < 2 || (s->xvel|s->zvel) == 0)
@ -3050,8 +3065,9 @@ ACTOR_STATIC void G_MoveWeapons(void)
s->zvel = 0; s->zvel = 0;
} }
if ((j&49152) == 49152) switch (j&49152)
{ {
case 49152:
j &= (MAXSPRITES-1); j &= (MAXSPRITES-1);
if (s->picnum == FREEZEBLAST && sprite[j].pal == 1) if (s->picnum == FREEZEBLAST && sprite[j].pal == 1)
@ -3075,9 +3091,9 @@ ACTOR_STATIC void G_MoveWeapons(void)
if (s->picnum == SPIT) if (s->picnum == SPIT)
P_HandleBeingSpitOn(g_player[p].ps); P_HandleBeingSpitOn(g_player[p].ps);
} }
} break;
else if ((j&49152) == 32768)
{ case 32768:
j &= (MAXWALLS-1); j &= (MAXWALLS-1);
if (s->picnum != RPG && s->picnum != FREEZEBLAST && s->picnum != SPIT && if (s->picnum != RPG && s->picnum != FREEZEBLAST && s->picnum != SPIT &&
@ -3105,9 +3121,9 @@ ACTOR_STATIC void G_MoveWeapons(void)
goto BOLT; goto BOLT;
} }
} }
} break;
else if ((j&49152) == 16384)
{ case 16384:
setsprite(i, &davect); setsprite(i, &davect);
if (s->zvel < 0) if (s->zvel < 0)
@ -3123,20 +3139,34 @@ ACTOR_STATIC void G_MoveWeapons(void)
{ {
A_DoProjectileBounce(i); A_DoProjectileBounce(i);
A_SetSprite(i, CLIPMASK1); A_SetSprite(i, CLIPMASK1);
s->extra >>= 1; s->extra >>= 1;
s->yvel--;
if (s->xrepeat > 8) if (s->xrepeat > 8)
{
s->xrepeat -= 2; s->xrepeat -= 2;
if (s->yrepeat > 8) if (s->yrepeat > 8)
s->yrepeat -= 2; s->yrepeat -= 2;
s->yvel--;
goto BOLT;
}
} }
if (s->picnum != SPIT) goto BOLT;
{ }
if (s->picnum == RPG) break;
default:
break;
}
switch (DYNAMICTILEMAP(s->picnum))
{ {
case SPIT__STATIC:
case COOLEXPLOSION1__STATIC:
case FREEZEBLAST__STATIC:
case FIRELASER__STATIC:
break;
case RPG__STATIC:
k = A_Spawn(i, EXPLOSION2); k = A_Spawn(i, EXPLOSION2);
A_PlaySound(RPG_EXPLODE, k); A_PlaySound(RPG_EXPLODE, k);
Bmemcpy(&sprite[k], &davect, sizeof(vec3_t)); Bmemcpy(&sprite[k], &davect, sizeof(vec3_t));
@ -3167,15 +3197,15 @@ ACTOR_STATIC void G_MoveWeapons(void)
x = s->extra+(g_globalRandom&3); x = s->extra+(g_globalRandom&3);
A_RadiusDamage(i, (g_rpgBlastRadius>>1), x>>2, x>>1, x-(x>>2), x); A_RadiusDamage(i, (g_rpgBlastRadius>>1), x>>2, x>>1, x-(x>>2), x);
} }
} break;
else if (s->picnum == SHRINKSPARK)
{ case SHRINKSPARK__STATIC:
A_Spawn(i, SHRINKEREXPLOSION); A_Spawn(i, SHRINKEREXPLOSION);
A_PlaySound(SHRINKER_HIT, i); A_PlaySound(SHRINKER_HIT, i);
A_RadiusDamage(i, g_shrinkerBlastRadius, 0, 0, 0, 0); A_RadiusDamage(i, g_shrinkerBlastRadius, 0, 0, 0, 0);
} break;
else if (s->picnum != COOLEXPLOSION1 && s->picnum != FREEZEBLAST && s->picnum != FIRELASER)
{ default:
k = A_Spawn(i, EXPLOSION2); k = A_Spawn(i, EXPLOSION2);
sprite[k].xrepeat = sprite[k].yrepeat = s->xrepeat>>1; sprite[k].xrepeat = sprite[k].yrepeat = s->xrepeat>>1;
if ((j&49152) == 16384) if ((j&49152) == 16384)
@ -3186,7 +3216,7 @@ ACTOR_STATIC void G_MoveWeapons(void)
sprite[k].z += (72<<8); sprite[k].z += (72<<8);
} }
} }
} break;
} }
if (s->picnum != COOLEXPLOSION1) if (s->picnum != COOLEXPLOSION1)

View file

@ -289,6 +289,7 @@ enum pflags_t {
PROJECTILE_FORCEIMPACT = 0x00040000, PROJECTILE_FORCEIMPACT = 0x00040000,
PROJECTILE_REALCLIPDIST = 0x00080000, PROJECTILE_REALCLIPDIST = 0x00080000,
PROJECTILE_ACCURATE = 0x00100000, PROJECTILE_ACCURATE = 0x00100000,
PROJECTILE_TYPE_MASK = PROJECTILE_HITSCAN|PROJECTILE_RPG|PROJECTILE_KNEE|PROJECTILE_BLOOD,
}; };
extern tiledata_t g_tile[MAXTILES]; extern tiledata_t g_tile[MAXTILES];

View file

@ -821,28 +821,274 @@ static void Proj_HandleKnee(hitdata_t *hit, int32_t i, int32_t p, int32_t atwith
} }
#define MinibossScale(s) (((s)*sprite[i].yrepeat)/80) #define MinibossScale(s) (((s)*sprite[i].yrepeat)/80)
int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel)
static int32_t A_ShootCustom(const int32_t i, const int32_t atwith, int16_t sa, vec3_t * const srcvect)
{ {
int16_t sa; /* Custom projectiles */
projectile_t *const proj = &ProjectileData[atwith];
int32_t j, k = -1, l; int32_t j, k = -1, l;
int32_t vel, zvel = 0; int32_t vel, zvel = 0;
hitdata_t hit; hitdata_t hit;
vec3_t srcvect;
spritetype *const s = &sprite[i]; spritetype *const s = &sprite[i];
const int16_t sect = s->sectnum; const int16_t sect = s->sectnum;
const int32_t p = (s->picnum == APLAYER) ? s->yvel : -1; const int32_t p = (s->picnum == APLAYER) ? s->yvel : -1;
DukePlayer_t *const ps = p >= 0 ? g_player[p].ps : NULL; DukePlayer_t *const ps = p >= 0 ? g_player[p].ps : NULL;
#ifdef POLYMER
if (proj->flashcolor)
{
int32_t x = ((sintable[(s->ang + 512) & 2047]) >> 7), y = ((sintable[(s->ang) & 2047]) >> 7);
s->x += x;
s->y += y;
G_AddGameLight(0, i, PHEIGHT, 8192, proj->flashcolor, PR_LIGHT_PRIO_MAX_GAME);
actor[i].lightcount = 2;
s->x -= x;
s->y -= y;
}
#endif // POLYMER
if (proj->offset == 0)
proj->offset = 1;
switch (proj->workslike & PROJECTILE_TYPE_MASK)
{
case PROJECTILE_HITSCAN:
if (s->extra >= 0) s->shade = proj->shade;
if (p >= 0)
P_PreFireHitscan(i, p, atwith, srcvect, &zvel, &sa,
proj->workslike & PROJECTILE_ACCURATE_AUTOAIM,
!(proj->workslike & PROJECTILE_ACCURATE));
else
A_PreFireHitscan(s, srcvect, &zvel, &sa,
!(proj->workslike & PROJECTILE_ACCURATE));
if (Proj_DoHitscan(i, (proj->cstat >= 0) ? proj->cstat : 256 + 1,
srcvect, zvel, sa, &hit))
return -1;
if (proj->range > 0 && klabs(srcvect->x - hit.pos.x) + klabs(srcvect->y - hit.pos.y) > proj->range)
return -1;
if (proj->trail >= 0)
A_HitscanProjTrail(srcvect, &hit.pos, sa, atwith);
if (proj->workslike & PROJECTILE_WATERBUBBLES)
{
if ((krand() & 15) == 0 && sector[hit.sect].lotag == ST_2_UNDERWATER)
A_DoWaterTracers(hit.pos.x, hit.pos.y, hit.pos.z,
srcvect->x, srcvect->y, srcvect->z, 8 - (ud.multimode >> 1));
}
if (p >= 0)
{
k = Proj_InsertShotspark(&hit, i, atwith, 10, sa, Proj_GetExtra(atwith));
if (P_PostFireHitscan(p, k, &hit, i, atwith, zvel,
atwith, proj->decal, atwith, 1 + 2) < 0)
return -1;
}
else
{
k = A_PostFireHitscan(&hit, i, atwith, sa, Proj_GetExtra(atwith),
atwith, atwith);
}
if ((krand() & 255) < 4 && proj->isound >= 0)
S_PlaySound3D(proj->isound, k, &hit.pos);
return -1;
case PROJECTILE_RPG:
if (s->extra >= 0) s->shade = proj->shade;
vel = proj->vel;
j = -1;
if (p >= 0)
{
j = GetAutoAimAngle(i, p, atwith, 8 << 8, 0 + 2, srcvect, vel, &zvel, &sa);
if (j < 0)
zvel = (100 - ps->horiz - ps->horizoff)*(proj->vel / 8);
if (proj->sound >= 0)
A_PlaySound(proj->sound, i);
}
else
{
if (!(proj->workslike & PROJECTILE_NOAIM))
{
j = A_FindPlayer(s, NULL);
sa = getangle(g_player[j].ps->opos.x - srcvect->x, g_player[j].ps->opos.y - srcvect->y);
l = safeldist(g_player[j].ps->i, s);
zvel = ((g_player[j].ps->opos.z - srcvect->z)*vel) / l;
if (A_CheckEnemySprite(s) && (s->hitag&face_player_smart))
sa = s->ang + (krand() & 31) - 16;
}
}
if (p >= 0 && j >= 0)
l = j;
else l = -1;
if (numplayers > 1 && g_netClient) return -1;
zvel = A_GetShootZvel(zvel);
j = A_InsertSprite(sect,
srcvect->x + (sintable[(348 + sa + 512) & 2047] / proj->offset),
srcvect->y + (sintable[(sa + 348) & 2047] / proj->offset),
srcvect->z - (1 << 8), atwith, 0, 14, 14, sa, vel, zvel, i, 4);
sprite[j].xrepeat = proj->xrepeat;
sprite[j].yrepeat = proj->yrepeat;
if (proj->extra_rand > 0)
sprite[j].extra += (krand()&proj->extra_rand);
if (!(proj->workslike & PROJECTILE_BOUNCESOFFWALLS))
sprite[j].yvel = l;
else
{
if (proj->bounces >= 1) sprite[j].yvel = proj->bounces;
else sprite[j].yvel = g_numFreezeBounces;
sprite[j].zvel -= (2 << 4);
}
if (proj->cstat >= 0) sprite[j].cstat = proj->cstat;
else sprite[j].cstat = 128;
if (proj->clipdist != 255) sprite[j].clipdist = proj->clipdist;
else sprite[j].clipdist = 40;
{
int32_t picnum = sprite[j].picnum; // why?
Bmemcpy(&SpriteProjectile[j], &ProjectileData[picnum], sizeof(projectile_t));
}
return j;
case PROJECTILE_KNEE:
if (p >= 0)
{
zvel = (100 - ps->horiz - ps->horizoff) << 5;
srcvect->z += (6 << 8);
sa += 15;
}
else if (!(proj->workslike & PROJECTILE_NOAIM))
{
int32_t x;
j = g_player[A_FindPlayer(s, &x)].ps->i;
zvel = ((sprite[j].z - srcvect->z) << 8) / (x + 1);
sa = getangle(sprite[j].x - srcvect->x, sprite[j].y - srcvect->y);
}
Proj_DoHitscan(i, 0, srcvect, zvel, sa, &hit);
if (hit.sect < 0) return -1;
if (proj->range == 0)
proj->range = 1024;
if (proj->range > 0 && klabs(srcvect->x - hit.pos.x) + klabs(srcvect->y - hit.pos.y) > proj->range)
return -1;
Proj_HandleKnee(&hit, i, p, atwith, sa,
proj, atwith,
proj->extra_rand,
proj->spawns, proj->sound);
return -1;
case PROJECTILE_BLOOD:
sa += 64 - (krand() & 127);
if (p < 0) sa += 1024;
zvel = 1024 - (krand() & 2047);
Proj_DoHitscan(i, 0, srcvect, zvel, sa, &hit);
if (proj->range == 0)
proj->range = 1024;
if (Proj_CheckBlood(srcvect, &hit, proj->range,
mulscale3(proj->yrepeat, tilesizy[proj->decal]) << 8))
{
const walltype *const hitwal = &wall[hit.wall];
if (FindDistance2D(hitwal->x - wall[hitwal->point2].x, hitwal->y - wall[hitwal->point2].y) >
(mulscale3(proj->xrepeat + 8, tilesizx[proj->decal])))
{
if (SectorContainsSE13(hitwal->nextsector))
return -1;
if (hitwal->nextwall >= 0 && wall[hitwal->nextwall].hitag != 0)
return -1;
if (hitwal->hitag == 0 && proj->decal >= 0)
{
k = A_Spawn(i, proj->decal);
if (!A_CheckSpriteFlags(k, SPRITE_DECAL))
actor[k].flags |= SPRITE_DECAL;
sprite[k].xvel = -1;
sprite[k].ang = getangle(hitwal->x - wall[hitwal->point2].x,
hitwal->y - wall[hitwal->point2].y) + 512;
Bmemcpy(&sprite[k], &hit.pos, sizeof(vec3_t));
Proj_DoRandDecalSize(k, atwith);
sprite[k].z += sprite[k].yrepeat << 8;
// sprite[k].cstat = 16+(krand()&12);
sprite[k].cstat = 16;
if (krand() & 1)
sprite[k].cstat |= 4;
if (krand() & 1)
sprite[k].cstat |= 8;
sprite[k].shade = sector[sprite[k].sectnum].floorshade;
sprite[k].x -= sintable[(sprite[k].ang + 2560) & 2047] >> 13;
sprite[k].y -= sintable[(sprite[k].ang + 2048) & 2047] >> 13;
A_SetSprite(k, CLIPMASK0);
A_AddToDeleteQueue(k);
changespritestat(k, 5);
}
}
}
return -1;
default:
return -1;
}
}
int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel)
{
int16_t sa;
vec3_t srcvect;
spritetype *const s = &sprite[i];
const int32_t p = (s->picnum == APLAYER) ? s->yvel : -1;
DukePlayer_t *const ps = p >= 0 ? g_player[p].ps : NULL;
Bassert(atwith >= 0);
if (override_zvel != SHOOT_HARDCODED_ZVEL) if (override_zvel != SHOOT_HARDCODED_ZVEL)
{ {
g_overrideShootZvel = 1; g_overrideShootZvel = 1;
g_shootZvel = override_zvel; g_shootZvel = override_zvel;
} }
else else
{
g_overrideShootZvel = 0; g_overrideShootZvel = 0;
}
if (s->picnum == APLAYER) if (s->picnum == APLAYER)
{ {
@ -870,7 +1116,6 @@ int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel)
} }
#ifdef POLYMER #ifdef POLYMER
if (atwith >= 0)
switch (DYNAMICTILEMAP(atwith)) switch (DYNAMICTILEMAP(atwith))
{ {
case FIRELASER__STATIC: case FIRELASER__STATIC:
@ -895,254 +1140,14 @@ int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel)
} }
if (A_CheckSpriteTileFlags(atwith, SPRITE_PROJECTILE)) if (A_CheckSpriteTileFlags(atwith, SPRITE_PROJECTILE))
{ return A_ShootCustom(i, atwith, sa, &srcvect);
/* Custom projectiles */
projectile_t *const proj = (Bassert(atwith >= 0), &ProjectileData[atwith]);
#ifdef POLYMER
if (proj->flashcolor)
{
int32_t x = ((sintable[(s->ang+512)&2047])>>7), y = ((sintable[(s->ang)&2047])>>7);
s-> x += x;
s-> y += y;
G_AddGameLight(0, i, PHEIGHT, 8192, proj->flashcolor,PR_LIGHT_PRIO_MAX_GAME);
actor[i].lightcount = 2;
s-> x -= x;
s-> y -= y;
}
#endif // POLYMER
if (proj->offset == 0)
proj->offset = 1;
if (proj->workslike & PROJECTILE_BLOOD || proj->workslike & PROJECTILE_KNEE)
{
if (proj->workslike & PROJECTILE_BLOOD)
{
sa += 64 - (krand()&127);
if (p < 0) sa += 1024;
zvel = 1024-(krand()&2047);
}
if (proj->workslike & PROJECTILE_KNEE)
{
if (p >= 0)
{
zvel = (100-ps->horiz-ps->horizoff)<<5;
srcvect.z += (6<<8);
sa += 15;
}
else if (!(proj->workslike & PROJECTILE_NOAIM))
{
int32_t x;
j = g_player[A_FindPlayer(s,&x)].ps->i;
zvel = ((sprite[j].z-srcvect.z)<<8) / (x+1);
sa = getangle(sprite[j].x-srcvect.x,sprite[j].y-srcvect.y);
}
}
Proj_DoHitscan(i, 0, &srcvect, zvel, sa, &hit);
if (proj->workslike & PROJECTILE_BLOOD)
{
if (proj->range == 0)
proj->range = 1024;
if (Proj_CheckBlood(&srcvect, &hit, proj->range,
mulscale3(proj->yrepeat, tilesizy[proj->decal])<<8))
{
const walltype *const hitwal = &wall[hit.wall];
if (FindDistance2D(hitwal->x-wall[hitwal->point2].x, hitwal->y-wall[hitwal->point2].y) >
(mulscale3(proj->xrepeat+8, tilesizx[proj->decal])))
{
if (SectorContainsSE13(hitwal->nextsector))
return -1;
if (hitwal->nextwall >= 0 && wall[hitwal->nextwall].hitag != 0)
return -1;
if (hitwal->hitag == 0)
{
if (proj->decal >= 0)
{
k = A_Spawn(i,proj->decal);
if (!A_CheckSpriteFlags(k, SPRITE_DECAL))
actor[k].flags |= SPRITE_DECAL;
sprite[k].xvel = -1;
sprite[k].ang = getangle(hitwal->x-wall[hitwal->point2].x,
hitwal->y-wall[hitwal->point2].y)+512;
Bmemcpy(&sprite[k], &hit.pos, sizeof(vec3_t));
Proj_DoRandDecalSize(k, atwith);
sprite[k].z += sprite[k].yrepeat<<8;
// sprite[k].cstat = 16+(krand()&12);
sprite[k].cstat = 16;
if (krand()&1)
sprite[k].cstat |= 4;
if (krand()&1)
sprite[k].cstat |= 8;
sprite[k].shade = sector[sprite[k].sectnum].floorshade;
sprite[k].x -= sintable[(sprite[k].ang+2560)&2047]>>13;
sprite[k].y -= sintable[(sprite[k].ang+2048)&2047]>>13;
A_SetSprite(k,CLIPMASK0);
A_AddToDeleteQueue(k);
changespritestat(k,5);
}
}
}
}
return -1;
}
if (hit.sect < 0) return -1;
if (proj->range == 0 && (proj->workslike & PROJECTILE_KNEE))
proj->range = 1024;
if (proj->range > 0 && klabs(srcvect.x-hit.pos.x)+klabs(srcvect.y-hit.pos.y) > proj->range)
return -1;
Proj_HandleKnee(&hit, i, p, atwith, sa,
proj, atwith,
proj->extra_rand,
proj->spawns, proj->sound);
return -1;
}
if (proj->workslike & PROJECTILE_HITSCAN)
{
if (s->extra >= 0) s->shade = proj->shade;
if (p >= 0)
P_PreFireHitscan(i, p, atwith, &srcvect, &zvel, &sa,
proj->workslike & PROJECTILE_ACCURATE_AUTOAIM,
!(proj->workslike & PROJECTILE_ACCURATE));
else
A_PreFireHitscan(s, &srcvect, &zvel, &sa,
!(proj->workslike & PROJECTILE_ACCURATE));
if (Proj_DoHitscan(i, (proj->cstat >= 0) ? proj->cstat : 256+1,
&srcvect, zvel, sa, &hit))
return -1;
if (proj->range > 0 && klabs(srcvect.x-hit.pos.x)+klabs(srcvect.y-hit.pos.y) > proj->range)
return -1;
if (proj->trail >= 0)
A_HitscanProjTrail(&srcvect,&hit.pos,sa,atwith);
if (proj->workslike & PROJECTILE_WATERBUBBLES)
{
if ((krand()&15) == 0 && sector[hit.sect].lotag == ST_2_UNDERWATER)
A_DoWaterTracers(hit.pos.x,hit.pos.y,hit.pos.z,
srcvect.x,srcvect.y,srcvect.z,8-(ud.multimode>>1));
}
if (p >= 0)
{
k = Proj_InsertShotspark(&hit, i, atwith, 10, sa, Proj_GetExtra(atwith));
if (P_PostFireHitscan(p, k, &hit, i, atwith, zvel,
atwith, proj->decal, atwith, 1+2) < 0)
return -1;
}
else else
{ {
k = A_PostFireHitscan(&hit, i, atwith, sa, Proj_GetExtra(atwith), int32_t j, k = -1, l;
atwith, atwith); int32_t vel, zvel = 0;
} hitdata_t hit;
const int16_t sect = s->sectnum;
if ((krand()&255) < 4 && proj->isound >= 0)
S_PlaySound3D(proj->isound, k, &hit.pos);
return -1;
}
if (proj->workslike & PROJECTILE_RPG)
{
if (s->extra >= 0) s->shade = proj->shade;
vel = proj->vel;
j = -1;
if (p >= 0)
{
j = GetAutoAimAngle(i, p, atwith, 8<<8, 0+2, &srcvect, vel, &zvel, &sa);
if (j < 0)
zvel = (100-ps->horiz-ps->horizoff)*(proj->vel/8);
if (proj->sound >= 0)
A_PlaySound(proj->sound,i);
}
else
{
if (!(proj->workslike & PROJECTILE_NOAIM))
{
j = A_FindPlayer(s, NULL);
sa = getangle(g_player[j].ps->opos.x-srcvect.x,g_player[j].ps->opos.y-srcvect.y);
l = safeldist(g_player[j].ps->i, s);
zvel = ((g_player[j].ps->opos.z-srcvect.z)*vel) / l;
if (A_CheckEnemySprite(s) && (s->hitag&face_player_smart))
sa = s->ang+(krand()&31)-16;
}
}
if (p >= 0 && j >= 0)
l = j;
else l = -1;
if (numplayers > 1 && g_netClient) return -1;
zvel = A_GetShootZvel(zvel);
j = A_InsertSprite(sect,
srcvect.x+(sintable[(348+sa+512)&2047]/proj->offset),
srcvect.y+(sintable[(sa+348)&2047]/proj->offset),
srcvect.z-(1<<8),atwith,0,14,14,sa,vel,zvel,i,4);
sprite[j].xrepeat=proj->xrepeat;
sprite[j].yrepeat=proj->yrepeat;
if (proj->extra_rand > 0)
sprite[j].extra += (krand()&proj->extra_rand);
if (!(proj->workslike & PROJECTILE_BOUNCESOFFWALLS))
sprite[j].yvel = l;
else
{
if (proj->bounces >= 1) sprite[j].yvel = proj->bounces;
else sprite[j].yvel = g_numFreezeBounces;
sprite[j].zvel -= (2<<4);
}
if (proj->cstat >= 0) sprite[j].cstat = proj->cstat;
else sprite[j].cstat = 128;
if (proj->clipdist != 255) sprite[j].clipdist = proj->clipdist;
else sprite[j].clipdist = 40;
{
int32_t picnum = sprite[j].picnum;
Bmemcpy(&SpriteProjectile[j], &ProjectileData[picnum], sizeof(projectile_t));
}
return j;
}
}
else if (atwith >= 0)
{
switch (DYNAMICTILEMAP(atwith)) switch (DYNAMICTILEMAP(atwith))
{ {
case BLOODSPLAT1__STATIC: case BLOODSPLAT1__STATIC:
@ -1214,7 +1219,6 @@ int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel)
case SHOTSPARK1__STATIC: case SHOTSPARK1__STATIC:
case SHOTGUN__STATIC: case SHOTGUN__STATIC:
case CHAINGUN__STATIC: case CHAINGUN__STATIC:
if (s->extra >= 0) s->shade = -96; if (s->extra >= 0) s->shade = -96;
if (p >= 0) if (p >= 0)
@ -1252,7 +1256,6 @@ int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel)
return -1; return -1;
case GROWSPARK__STATIC: case GROWSPARK__STATIC:
if (p >= 0) if (p >= 0)
P_PreFireHitscan(i, p, atwith, &srcvect, &zvel, &sa, 1, 1); P_PreFireHitscan(i, p, atwith, &srcvect, &zvel, &sa, 1, 1);
else else
@ -1286,20 +1289,21 @@ int32_t A_ShootWithZvel(int32_t i, int32_t atwith, int32_t override_zvel)
if (s->extra >= 0) s->shade = -96; if (s->extra >= 0) s->shade = -96;
if (atwith == SPIT) vel = 292; switch (atwith)
else
{
if (atwith == COOLEXPLOSION1)
{ {
case SPIT__STATIC:
vel = 292;
break;
case COOLEXPLOSION1__STATIC:
if (s->picnum == BOSS2) vel = 644; if (s->picnum == BOSS2) vel = 644;
else vel = 348; else vel = 348;
srcvect.z -= (4<<7); srcvect.z -= (4<<7);
} break;
else case FIRELASER__STATIC:
{ default:
vel = 840; vel = 840;
srcvect.z -= (4<<7); srcvect.z -= (4<<7);
} break;
} }
if (p >= 0) if (p >= 0)
@ -1690,13 +1694,8 @@ static int32_t P_DisplayFist(int32_t gs,int32_t snum)
return 1; return 1;
} }
#define DRAWEAP_CENTER 262144 #define DRAWEAP_CENTER 262144
#define weapsc(sc) scale(sc, ud.weaponscale, 100)
static inline int32_t weapsc(int32_t sc)
{
return scale(sc, ud.weaponscale, 100);
}
static int32_t g_dts_yadd; static int32_t g_dts_yadd;