Implement hardcoded WT stuff

Includes the new weapon, enemy projectiles, and breakable objects.

Patch from Nuke.YKT.

I edited it some, mostly to add the proper "if (WORLDTOUR)" checks.

From-SVN: r8788
# Conflicts:
#	source/duke3d/src/namesdyn.cpp
This commit is contained in:
Evan Ramos 2020-03-29 08:41:12 +00:00 committed by Christoph Oelckers
parent 0d576cf798
commit e6940cd591
14 changed files with 732 additions and 20 deletions

View file

@ -24,6 +24,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define actors_c_ #define actors_c_
#ifndef EDUKE32_STANDALONE
#include <map>
#endif
#include "duke3d.h" #include "duke3d.h"
#include "sounds.h" #include "sounds.h"
@ -107,6 +111,15 @@ void A_RadiusDamageObject_Internal(int const spriteNum, int const otherSprite, i
auto const pSprite = (uspriteptr_t)&sprite[spriteNum]; auto const pSprite = (uspriteptr_t)&sprite[spriteNum];
auto const pOther = &sprite[otherSprite]; auto const pOther = &sprite[otherSprite];
#ifndef EDUKE32_STANDALONE
if (WORLDTOUR && pSprite->picnum == FLAMETHROWERFLAME)
{
if (sprite[pSprite->owner].picnum == FIREFLY && pOther->picnum == FIREFLY)
return;
if (sprite[pSprite->owner].picnum == BOSS5 && pOther->picnum == BOSS5)
return;
}
#endif
// DEFAULT, ZOMBIEACTOR, MISC // DEFAULT, ZOMBIEACTOR, MISC
if (pOther->statnum == STAT_DEFAULT || pOther->statnum == STAT_ZOMBIEACTOR || pOther->statnum == STAT_MISC if (pOther->statnum == STAT_DEFAULT || pOther->statnum == STAT_ZOMBIEACTOR || pOther->statnum == STAT_MISC
@ -166,11 +179,16 @@ void A_RadiusDamageObject_Internal(int const spriteNum, int const otherSprite, i
#endif #endif
) )
dmgActor.picnum = pSprite->picnum; dmgActor.picnum = pSprite->picnum;
#ifndef EDUKE32_STANDALONE
else if (WORLDTOUR && (pSprite->picnum == FLAMETHROWERFLAME || pSprite->picnum == LAVAPOOL
|| (pSprite->picnum == FIREBALL && sprite[pSprite->owner].picnum == APLAYER)))
dmgActor.picnum = FLAMETHROWERFLAME;
#endif
else else
dmgActor.picnum = RADIUSEXPLOSION; dmgActor.picnum = RADIUSEXPLOSION;
#ifndef EDUKE32_STANDALONE #ifndef EDUKE32_STANDALONE
if (pSprite->picnum != SHRINKSPARK) if (pSprite->picnum != SHRINKSPARK && (!WORLDTOUR || pSprite->picnum != LAVAPOOL))
#endif #endif
{ {
// this is really weird // this is really weird
@ -3143,6 +3161,17 @@ ACTOR_STATIC void Proj_MoveCustom(int const spriteNum)
} }
} }
#ifndef EDUKE32_STANDALONE
struct SpriteTracerData
{
int32_t x, y, z;
int32_t xVel, yVel, zVel;
SpriteTracerData() : x(0), y(0), z(0), xVel(0), yVel(0), zVel(0) { }
};
std::map<int, SpriteTracerData> tracerData;
#endif
ACTOR_STATIC void G_MoveWeapons(void) ACTOR_STATIC void G_MoveWeapons(void)
{ {
int spriteNum = headspritestat[STAT_PROJECTILE]; int spriteNum = headspritestat[STAT_PROJECTILE];
@ -3194,6 +3223,10 @@ ACTOR_STATIC void G_MoveWeapons(void)
DELETE_SPRITE_AND_CONTINUE(spriteNum); DELETE_SPRITE_AND_CONTINUE(spriteNum);
} }
fallthrough__; fallthrough__;
case FIREBALL__STATIC:
if (!WORLDTOUR && pSprite->picnum == FIREBALL)
break;
fallthrough__;
case SHRINKSPARK__STATIC: case SHRINKSPARK__STATIC:
case RPG__STATIC: case RPG__STATIC:
case FIRELASER__STATIC: case FIRELASER__STATIC:
@ -3220,6 +3253,8 @@ ACTOR_STATIC void G_MoveWeapons(void)
A_GetZLimits(spriteNum); A_GetZLimits(spriteNum);
int const fireball = (WORLDTOUR && pSprite->picnum == FIREBALL && sprite[pSprite->owner].picnum != FIREBALL);
if (pSprite->picnum == RPG && actor[spriteNum].picnum != BOSS2 && pSprite->xrepeat >= 10 if (pSprite->picnum == RPG && actor[spriteNum].picnum != BOSS2 && pSprite->xrepeat >= 10
&& sector[pSprite->sectnum].lotag != ST_2_UNDERWATER && sector[pSprite->sectnum].lotag != ST_2_UNDERWATER
&& g_scriptVersion >= 13) && g_scriptVersion >= 13)
@ -3227,6 +3262,48 @@ ACTOR_STATIC void G_MoveWeapons(void)
int const newSprite = A_Spawn(spriteNum, SMALLSMOKE); int const newSprite = A_Spawn(spriteNum, SMALLSMOKE);
sprite[newSprite].z += (1 << 8); sprite[newSprite].z += (1 << 8);
} }
if (pSprite->picnum == FIREBALL)
{
if (sector[pSprite->sectnum].lotag == ST_2_UNDERWATER) { DELETE_SPRITE_AND_CONTINUE(spriteNum); }
if (fireball)
{
if (actor[spriteNum].t_data[0] >= 1 && actor[spriteNum].t_data[0] < 6)
{
float t = 1.f - 0.2 * actor[spriteNum].t_data[0];
int j = A_Spawn(spriteNum, FIREBALL);
spritetype* sj = &sprite[j];
sj->xvel = pSprite->xvel;
sj->yvel = pSprite->yvel;
sj->zvel = pSprite->zvel;
if (actor[spriteNum].t_data[0] > 1)
{
SpriteTracerData t = tracerData[actor[spriteNum].t_data[1]];
sj->x = t.x;
sj->y = t.y;
sj->z = t.z;
sj->xvel = t.xVel;
sj->yvel = t.yVel;
sj->zvel = t.zVel;
}
sj->xrepeat = sj->yrepeat = t * pSprite->xrepeat;
sj->cstat = pSprite->cstat;
sj->extra = 0;
actor[spriteNum].t_data[1] = j;
SpriteTracerData tt;
tt.x = sj->x;
tt.y = sj->y;
tt.z = sj->z;
tt.xVel = sj->xvel;
tt.yVel = sj->yvel;
tt.zVel = sj->zvel;
tracerData[actor[spriteNum].t_data[1]] = tt;
changespritestat(j, 4);
}
actor[spriteNum].t_data[0]++;
}
if (pSprite->zvel < 15000)
pSprite->zvel += 200;
}
vec3_t const tmpvect = { (spriteXvel * (sintable[(pSprite->ang + 512) & 2047])) >> 14 >> (int)!projectileMoved, vec3_t const tmpvect = { (spriteXvel * (sintable[(pSprite->ang + 512) & 2047])) >> 14 >> (int)!projectileMoved,
(spriteXvel * (sintable[pSprite->ang & 2047])) >> 14 >> (int)!projectileMoved, spriteZvel >> (int)!projectileMoved }; (spriteXvel * (sintable[pSprite->ang & 2047])) >> 14 >> (int)!projectileMoved, spriteZvel >> (int)!projectileMoved };
@ -3289,7 +3366,8 @@ ACTOR_STATIC void G_MoveWeapons(void)
DELETE_SPRITE_AND_CONTINUE(spriteNum); DELETE_SPRITE_AND_CONTINUE(spriteNum);
} }
A_DamageObject(moveSprite, spriteNum); if (!WORLDTOUR || pSprite->picnum != FIREBALL || fireball)
A_DamageObject(moveSprite, spriteNum);
if (sprite[moveSprite].picnum == APLAYER) if (sprite[moveSprite].picnum == APLAYER)
{ {
@ -3305,6 +3383,7 @@ ACTOR_STATIC void G_MoveWeapons(void)
moveSprite &= (MAXWALLS - 1); moveSprite &= (MAXWALLS - 1);
if (pSprite->picnum != RPG && pSprite->picnum != FREEZEBLAST && pSprite->picnum != SPIT if (pSprite->picnum != RPG && pSprite->picnum != FREEZEBLAST && pSprite->picnum != SPIT
&& (!WORLDTOUR || pSprite->picnum != FIREBALL)
&& (wall[moveSprite].overpicnum == MIRROR || wall[moveSprite].picnum == MIRROR)) && (wall[moveSprite].overpicnum == MIRROR || wall[moveSprite].picnum == MIRROR))
{ {
Proj_BounceOffWall(pSprite, moveSprite); Proj_BounceOffWall(pSprite, moveSprite);
@ -3355,6 +3434,15 @@ ACTOR_STATIC void G_MoveWeapons(void)
goto next_sprite; goto next_sprite;
} }
if (pSprite->zvel >= 0 && fireball)
{
int lp = A_Spawn(spriteNum, LAVAPOOL);
sprite[lp].owner = sprite[spriteNum].owner;
sprite[lp].yvel = sprite[spriteNum].yvel;
actor[lp].owner = sprite[spriteNum].owner;
DELETE_SPRITE_AND_CONTINUE(spriteNum);
}
break; break;
default: break; default: break;
} }
@ -3408,6 +3496,10 @@ ACTOR_STATIC void G_MoveWeapons(void)
A_RadiusDamage(spriteNum, g_shrinkerRadius, 0, 0, 0, 0); A_RadiusDamage(spriteNum, g_shrinkerRadius, 0, 0, 0, 0);
break; break;
case FIREBALL__STATIC:
if (WORLDTOUR)
break;
fallthrough__;
default: default:
{ {
int const newSprite = A_Spawn(spriteNum, EXPLOSION2); int const newSprite = A_Spawn(spriteNum, EXPLOSION2);
@ -3424,6 +3516,12 @@ ACTOR_STATIC void G_MoveWeapons(void)
} }
} }
if (fireball)
{
int ex = A_Spawn(spriteNum, EXPLOSION2);
sprite[ex].xrepeat = sprite[ex].yrepeat = pSprite->xrepeat >> 1;
}
if (pSprite->picnum != COOLEXPLOSION1) if (pSprite->picnum != COOLEXPLOSION1)
DELETE_SPRITE_AND_CONTINUE(spriteNum); DELETE_SPRITE_AND_CONTINUE(spriteNum);
} }
@ -3945,6 +4043,108 @@ ACTOR_STATIC void G_MoveActors(void)
#ifndef EDUKE32_STANDALONE #ifndef EDUKE32_STANDALONE
switch (DYNAMICTILEMAP(switchPic)) switch (DYNAMICTILEMAP(switchPic))
{ {
case FLAMETHROWERFLAME__STATIC:
{
if (!WORLDTOUR)
goto next_sprite;
if (G_HaveActor(sprite[spriteNum].picnum))
{
int32_t playerDist;
int const playerNum = A_FindPlayer(pSprite, &playerDist);
A_Execute(spriteNum, playerNum, playerDist);
}
actor[spriteNum].t_data[0]++;
if (sector[pSprite->sectnum].lotag == ST_2_UNDERWATER)
{
int const newSprite = A_Spawn(spriteNum, EXPLOSION2);
sprite[newSprite].shade = 127;
DELETE_SPRITE_AND_CONTINUE(spriteNum);
}
int spriteXvel = pSprite->xvel;
int spriteZvel = pSprite->zvel;
vec3_t davect = pSprite->pos;
A_GetZLimits(spriteNum);
if (pSprite->xrepeat < 80)
{
pSprite->xrepeat += actor[spriteNum].t_data[0] / 6;
pSprite->yrepeat += actor[spriteNum].t_data[0] / 6;
}
pSprite->clipdist += actor[spriteNum].t_data[0] / 6;
if (actor[spriteNum].t_data[0] < 2)
actor[spriteNum].t_data[3] = krand() % 10;
if (actor[spriteNum].t_data[0] > 30)
{
int const newSprite = A_Spawn(spriteNum, EXPLOSION2);
sprite[newSprite].shade = 127;
DELETE_SPRITE_AND_CONTINUE(spriteNum);
}
vec3_t const tmpvect = { (spriteXvel * (sintable[(pSprite->ang + 512) & 2047])) >> 14,
(spriteXvel * (sintable[pSprite->ang & 2047])) >> 14, spriteZvel };
int moveSprite = A_MoveSprite(spriteNum, &tmpvect, CLIPMASK1);
actor[spriteNum].movflag = moveSprite;
if (pSprite->sectnum < 0)
DELETE_SPRITE_AND_CONTINUE(spriteNum);
if ((moveSprite & 49152) != 49152 && pSprite->picnum != FREEZEBLAST)
G_WeaponHitCeilingOrFloor(spriteNum, pSprite, &moveSprite);
if (moveSprite != 0)
{
switch (moveSprite & 49152)
{
case 49152:
moveSprite &= (MAXSPRITES - 1);
A_DamageObject(moveSprite, spriteNum);
if (sprite[moveSprite].picnum == APLAYER)
{
A_PlaySound(PISTOL_BODYHIT, moveSprite);
}
break;
case 32768:
moveSprite &= (MAXWALLS - 1);
setsprite(spriteNum, &davect);
A_DamageWall(spriteNum, moveSprite, pSprite->pos, pSprite->picnum);
break;
case 16384:
setsprite(spriteNum, &davect);
if (pSprite->zvel < 0)
Sect_DamageCeiling(spriteNum, pSprite->sectnum);
else if (pSprite->zvel > 0)
Sect_DamageFloor(spriteNum, pSprite->sectnum);
break;
default: break;
}
}
if (pSprite->xrepeat >= 10)
{
int const x = pSprite->extra;
A_RadiusDamage(spriteNum, g_rpgRadius, x >> 2, x >> 1, x - (x >> 2), x);
}
else
{
int const x = pSprite->extra + (g_globalRandom & 3);
A_RadiusDamage(spriteNum, (g_rpgRadius >> 1), x >> 2, x >> 1, x - (x >> 2), x);
}
goto next_sprite;
}
case DUCK__STATIC: case DUCK__STATIC:
case TARGET__STATIC: case TARGET__STATIC:
if (pSprite->cstat&32) if (pSprite->cstat&32)
@ -5247,6 +5447,17 @@ ACTOR_STATIC void G_MoveMisc(void) // STATNUM 5
} }
goto next_sprite; goto next_sprite;
#ifndef EDUKE32_STANDALONE
case ONFIRESMOKE__STATIC:
case ONFIRE__STATIC:
case BURNEDCORPSE__STATIC:
case LAVAPOOLBUBBLE__STATIC:
case WHISPYSMOKE__STATIC:
case LAVAPOOL__STATIC:
if (!WORLDTOUR)
goto next_sprite;
fallthrough__;
#endif
case EXPLOSION2__STATIC: case EXPLOSION2__STATIC:
case EXPLOSION2BOT__STATIC: case EXPLOSION2BOT__STATIC:
case FORCERIPPLE__STATIC: case FORCERIPPLE__STATIC:
@ -5706,6 +5917,34 @@ ACTOR_STATIC void G_MoveMisc(void) // STATNUM 5
A_SetSprite(spriteNum,CLIPMASK0); A_SetSprite(spriteNum,CLIPMASK0);
goto next_sprite; goto next_sprite;
case FIREFLYFLYINGEFFECT__STATIC:
if (WORLDTOUR && G_HaveActor(sprite[spriteNum].picnum))
{
int playerDist;
int const playerNum = A_FindPlayer(pSprite, &playerDist);
A_Execute(spriteNum, playerNum, playerDist);
spritetype *pPlayer = &sprite[g_player[playerNum].ps->i];
spritetype* pOwner = &sprite[pSprite->owner];
if (pOwner->picnum != FIREFLY) DELETE_SPRITE_AND_CONTINUE(spriteNum);
if (pOwner->xrepeat < 24 && pOwner->pal != 1)
pSprite->cstat &= ~32768;
else
pSprite->cstat |= 32768;
float dx = pOwner->x-pPlayer->x;
float dy = pOwner->y-pPlayer->y;
float dn = sqrt(dx*dx+dy*dy);
if (dn > 0.f)
{
dx /= dn;
dy /= dn;
}
pSprite->x = pOwner->x-int(dx*-10.f);
pSprite->y = pOwner->y-int(dy*-10.f);
pSprite->z = pOwner->z+0x800;
if (pOwner->extra <= 0) DELETE_SPRITE_AND_CONTINUE(spriteNum);
}
goto next_sprite;
} }
#endif #endif
} }

View file

@ -38,10 +38,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifdef EDUKE32_STANDALONE #ifdef EDUKE32_STANDALONE
#define VOLUMEALL (1) #define VOLUMEALL (1)
#define PLUTOPAK (1) #define PLUTOPAK (1)
#define WORLDTOUR (0)
#define VOLUMEONE (0) #define VOLUMEONE (0)
#else #else
#define VOLUMEALL (g_Shareware == 0) #define VOLUMEALL (g_Shareware == 0)
#define PLUTOPAK (g_scriptVersion >= 14) #define PLUTOPAK (g_scriptVersion >= 14)
#define WORLDTOUR (DUKE && g_scriptVersion >= 16)
#define VOLUMEONE (g_Shareware == 1) #define VOLUMEONE (g_Shareware == 1)
#endif #endif

View file

@ -1651,6 +1651,12 @@ int A_Spawn(int spriteNum, int tileNum)
changespritestat(newSprite, STAT_ACTOR); changespritestat(newSprite, STAT_ACTOR);
goto SPAWN_END; goto SPAWN_END;
case BOSS2STAYPUT__STATIC:
case BOSS3STAYPUT__STATIC:
case BOSS5STAYPUT__STATIC:
if (!WORLDTOUR)
break;
fallthrough__;
case OCTABRAINSTAYPUT__STATIC: case OCTABRAINSTAYPUT__STATIC:
case LIZTROOPSTAYPUT__STATIC: case LIZTROOPSTAYPUT__STATIC:
case PIGCOPSTAYPUT__STATIC: case PIGCOPSTAYPUT__STATIC:
@ -1661,15 +1667,20 @@ int A_Spawn(int spriteNum, int tileNum)
case BOSS4STAYPUT__STATIC: case BOSS4STAYPUT__STATIC:
pActor->stayput = pSprite->sectnum; pActor->stayput = pSprite->sectnum;
fallthrough__; fallthrough__;
case GREENSLIME__STATIC:
if (pSprite->picnum == GREENSLIME)
pSprite->extra = 1;
fallthrough__;
case BOSS5__STATIC:
case FIREFLY__STATIC:
if (!WORLDTOUR && (pSprite->picnum == BOSS5 || pSprite->picnum == FIREFLY))
break;
fallthrough__;
case BOSS1__STATIC: case BOSS1__STATIC:
case BOSS2__STATIC: case BOSS2__STATIC:
case BOSS3__STATIC: case BOSS3__STATIC:
case BOSS4__STATIC: case BOSS4__STATIC:
case ROTATEGUN__STATIC: case ROTATEGUN__STATIC:
case GREENSLIME__STATIC:
if (pSprite->picnum == GREENSLIME)
pSprite->extra = 1;
fallthrough__;
case DRONE__STATIC: case DRONE__STATIC:
case LIZTROOPONTOILET__STATIC: case LIZTROOPONTOILET__STATIC:
case LIZTROOPJUSTSIT__STATIC: case LIZTROOPJUSTSIT__STATIC:
@ -1710,12 +1721,14 @@ int A_Spawn(int spriteNum, int tileNum)
} }
if (pSprite->picnum == BOSS4STAYPUT || pSprite->picnum == BOSS1 || pSprite->picnum == BOSS2 || if (pSprite->picnum == BOSS4STAYPUT || pSprite->picnum == BOSS1 || pSprite->picnum == BOSS2 ||
pSprite->picnum == BOSS1STAYPUT || pSprite->picnum == BOSS3 || pSprite->picnum == BOSS4) pSprite->picnum == BOSS1STAYPUT || pSprite->picnum == BOSS3 || pSprite->picnum == BOSS4 ||
(WORLDTOUR && (pSprite->picnum == BOSS2STAYPUT || pSprite->picnum == BOSS3STAYPUT ||
pSprite->picnum == BOSS5STAYPUT || pSprite->picnum == BOSS5)))
{ {
if (spriteNum >= 0 && sprite[spriteNum].picnum == RESPAWN) if (spriteNum >= 0 && sprite[spriteNum].picnum == RESPAWN)
pSprite->pal = sprite[spriteNum].pal; pSprite->pal = sprite[spriteNum].pal;
if (pSprite->pal) if (pSprite->pal && (!WORLDTOUR || pSprite->pal != 22))
{ {
pSprite->clipdist = 80; pSprite->clipdist = 80;
pSprite->xrepeat = pSprite->yrepeat = 40; pSprite->xrepeat = pSprite->yrepeat = 40;
@ -1853,6 +1866,12 @@ int A_Spawn(int spriteNum, int tileNum)
changespritestat(newSprite, STAT_ZOMBIEACTOR); changespritestat(newSprite, STAT_ZOMBIEACTOR);
goto SPAWN_END; goto SPAWN_END;
case FLAMETHROWERSPRITE__STATIC:
case FLAMETHROWERAMMO__STATIC:
if (!WORLDTOUR)
break;
fallthrough__;
case ATOMICHEALTH__STATIC: case ATOMICHEALTH__STATIC:
case STEROIDS__STATIC: case STEROIDS__STATIC:
case HEATSENSOR__STATIC: case HEATSENSOR__STATIC:
@ -2070,6 +2089,10 @@ int A_Spawn(int spriteNum, int tileNum)
changespritestat(newSprite, STAT_MISC); changespritestat(newSprite, STAT_MISC);
goto SPAWN_END; goto SPAWN_END;
case LAVAPOOL__STATIC:
if (!WORLDTOUR)
break;
fallthrough__;
case BLOODPOOL__STATIC: case BLOODPOOL__STATIC:
case PUKE__STATIC: case PUKE__STATIC:
{ {
@ -2119,6 +2142,8 @@ int A_Spawn(int spriteNum, int tileNum)
pSprite->shade = 127; pSprite->shade = 127;
} }
pSprite->cstat |= 32; pSprite->cstat |= 32;
if (pSprite->picnum == LAVAPOOL)
pSprite->z = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y) - 200;
fallthrough__; fallthrough__;
} }
case FECES__STATIC: case FECES__STATIC:
@ -2344,6 +2369,10 @@ int A_Spawn(int spriteNum, int tileNum)
fallthrough__; fallthrough__;
#endif #endif
#ifndef EDUKE32_STANDALONE #ifndef EDUKE32_STANDALONE
case ONFIRE__STATIC:
if (!WORLDTOUR && pSprite->picnum == ONFIRE)
break;
fallthrough__;
case EXPLOSION2BOT__STATIC: case EXPLOSION2BOT__STATIC:
case BURNING__STATIC: case BURNING__STATIC:
case BURNING2__STATIC: case BURNING2__STATIC:
@ -2366,7 +2395,7 @@ int A_Spawn(int spriteNum, int tileNum)
} }
else if (pSprite->picnum == SHRINKEREXPLOSION) else if (pSprite->picnum == SHRINKEREXPLOSION)
pSprite->xrepeat = pSprite->yrepeat = 32; pSprite->xrepeat = pSprite->yrepeat = 32;
else if (pSprite->picnum == SMALLSMOKE) else if (pSprite->picnum == SMALLSMOKE || pSprite->picnum == ONFIRE)
{ {
// 64 "money" // 64 "money"
pSprite->xrepeat = pSprite->yrepeat = 24; pSprite->xrepeat = pSprite->yrepeat = 24;
@ -2384,6 +2413,14 @@ int A_Spawn(int spriteNum, int tileNum)
pSprite->z = floorZ-ZOFFSET4; pSprite->z = floorZ-ZOFFSET4;
} }
if (pSprite->picnum == ONFIRE)
{
pActor->bpos.x = pSprite->x += (krand()%256)-128;
pActor->bpos.y = pSprite->y += (krand()%256)-128;
pActor->bpos.z = pSprite->z -= krand()%10240;
pSprite->cstat |= 128;
}
changespritestat(newSprite, STAT_MISC); changespritestat(newSprite, STAT_MISC);
goto SPAWN_END; goto SPAWN_END;
@ -3094,6 +3131,41 @@ int A_Spawn(int spriteNum, int tileNum)
A_SetSprite(newSprite,CLIPMASK0); A_SetSprite(newSprite,CLIPMASK0);
goto SPAWN_END; goto SPAWN_END;
case LAVAPOOLBUBBLE__STATIC:
if (!WORLDTOUR)
break;
if (sprite[spriteNum].xrepeat >= 30)
{
pSprite->owner = spriteNum;
changespritestat(newSprite, STAT_MISC);
pSprite->xrepeat = pSprite->yrepeat = 1;
pSprite->x += (krand()%512)-256;
pSprite->y += (krand()%512)-256;
}
goto SPAWN_END;
case WHISPYSMOKE__STATIC:
if (!WORLDTOUR)
break;
pActor->bpos.x = pSprite->x += (krand()%256)-128;
pActor->bpos.y = pSprite->y += (krand()%256)-128;
pSprite->xrepeat = pSprite->yrepeat = 20;
changespritestat(newSprite, STAT_MISC);
goto SPAWN_END;
case FIREFLYFLYINGEFFECT__STATIC:
if (!WORLDTOUR)
break;
pSprite->owner = spriteNum;
changespritestat(newSprite, STAT_MISC);
pSprite->xrepeat = pSprite->yrepeat = 1;
goto SPAWN_END;
case E32_TILE5846__STATIC:
if (!WORLDTOUR)
break;
pSprite->extra = 150;
pSprite->cstat |= 257;
changespritestat(newSprite, STAT_ZOMBIEACTOR);
goto SPAWN_END;
default: default:
break; // NOT goto break; // NOT goto
} }
@ -5224,6 +5296,17 @@ static void A_InitEnemyFlags(void)
for (bssize_t i=ARRAY_SIZE(GreenSlimeFoodEnemies)-1; i>=0; i--) for (bssize_t i=ARRAY_SIZE(GreenSlimeFoodEnemies)-1; i>=0; i--)
SETFLAG(GreenSlimeFoodEnemies[i], SFLAG_GREENSLIMEFOOD); SETFLAG(GreenSlimeFoodEnemies[i], SFLAG_GREENSLIMEFOOD);
if (WORLDTOUR)
{
SETFLAG(FIREFLY, SFLAG_HARDCODED_BADGUY);
SETFLAG(BOSS5, SFLAG_NODAMAGEPUSH|SFLAG_HARDCODED_BADGUY);
SETFLAG(BOSS1STAYPUT, SFLAG_NODAMAGEPUSH|SFLAG_HARDCODED_BADGUY);
SETFLAG(BOSS2STAYPUT, SFLAG_NODAMAGEPUSH|SFLAG_HARDCODED_BADGUY);
SETFLAG(BOSS3STAYPUT, SFLAG_NODAMAGEPUSH|SFLAG_HARDCODED_BADGUY);
SETFLAG(BOSS4STAYPUT, SFLAG_NODAMAGEPUSH|SFLAG_HARDCODED_BADGUY);
SETFLAG(BOSS5STAYPUT, SFLAG_NODAMAGEPUSH|SFLAG_HARDCODED_BADGUY);
}
#endif #endif
} }
#undef SETFLAG #undef SETFLAG

View file

@ -2041,6 +2041,9 @@ void G_DoGameStartup(const int32_t *params)
g_deleteQueueSize = clamp(params[j++], 0, ARRAY_SSIZE(SpriteDeletionQueue)); g_deleteQueueSize = clamp(params[j++], 0, ARRAY_SSIZE(SpriteDeletionQueue));
g_tripbombLaserMode = params[j++]; g_tripbombLaserMode = params[j++];
} }
if (g_scriptVersion >= 16)
p0.max_ammo_amount[FLAMETHROWER_WEAPON] = params[j++];
} }
} }

View file

@ -1014,6 +1014,13 @@ static weapondata_t weapondefaults[MAX_WEAPONS] = {
GROWSPARK__STATIC, 0, 0, 0, 0, EXPANDERSHOOT__STATIC, 0, 0, GROWSPARK__STATIC, 0, 0, 0, 0, EXPANDERSHOOT__STATIC, 0, 0,
EJECT_CLIP__STATIC, INSERT_CLIP__STATIC, SELECT_WEAPON__STATIC, 216+(52<<8)+(20<<16) EJECT_CLIP__STATIC, INSERT_CLIP__STATIC, SELECT_WEAPON__STATIC, 216+(52<<8)+(20<<16)
}, },
{
FLAMETHROWER_WEAPON, 0, 0, 2, 16, 0,
WEAPON_RESET,
FIREBALL__STATIC, 0, 0, 0, FLAMETHROWER_INTRO__STATIC, FLAMETHROWER_INTRO__STATIC, 0, 0,
EJECT_CLIP__STATIC, INSERT_CLIP__STATIC, SELECT_WEAPON__STATIC, 216+(52<<8)+(20<<16)
},
#endif #endif
}; };

View file

@ -72,6 +72,7 @@ enum dukeweapon_t
FREEZE_WEAPON, FREEZE_WEAPON,
HANDREMOTE_WEAPON, // 10 HANDREMOTE_WEAPON, // 10
GROW_WEAPON, GROW_WEAPON,
FLAMETHROWER_WEAPON,
MAX_WEAPONS MAX_WEAPONS
}; };

View file

@ -640,6 +640,38 @@ LUNATIC_EXTERN struct dynitem g_dynTileList[] =
{ "WOMAN", DVPTR(WOMAN), WOMAN__STATIC }, { "WOMAN", DVPTR(WOMAN), WOMAN__STATIC },
{ "WOODENHORSE", DVPTR(WOODENHORSE), WOODENHORSE__STATIC }, { "WOODENHORSE", DVPTR(WOODENHORSE), WOODENHORSE__STATIC },
{ "XXXSTACY", DVPTR(XXXSTACY), XXXSTACY__STATIC }, { "XXXSTACY", DVPTR(XXXSTACY), XXXSTACY__STATIC },
{ "WIDESCREENSTATUSBAR", DVPTR(WIDESCREENSTATUSBAR), WIDESCREENSTATUSBAR__STATIC },
{ "RPGGUNWIDE", DVPTR(RPGGUNWIDE), RPGGUNWIDE__STATIC },
{ "FIRSTGUNRELOADWIDE", DVPTR(FIRSTGUNRELOADWIDE), FIRSTGUNRELOADWIDE__STATIC },
{ "FREEZEWIDE", DVPTR(FREEZEWIDE), FREEZEWIDE__STATIC },
{ "FREEZEFIREWIDE", DVPTR(FREEZEFIREWIDE), FREEZEFIREWIDE__STATIC },
{ "SHRINKERWIDE", DVPTR(SHRINKERWIDE), SHRINKERWIDE__STATIC },
{ "CRACKKNUCKLESWIDE", DVPTR(CRACKKNUCKLESWIDE), CRACKKNUCKLESWIDE__STATIC },
{ "FLAMETHROWERSPRITE", DVPTR(FLAMETHROWERSPRITE), FLAMETHROWERSPRITE__STATIC },
{ "FLAMETHROWERAMMO", DVPTR(FLAMETHROWERAMMO), FLAMETHROWERAMMO__STATIC },
{ "FLAMETHROWER", DVPTR(FLAMETHROWER), FLAMETHROWER__STATIC },
{ "FLAMETHROWERFIRE", DVPTR(FLAMETHROWERFIRE), FLAMETHROWERFIRE__STATIC },
{ "FLAMETHROWERFLAME", DVPTR(FLAMETHROWERFLAME), FLAMETHROWERFLAME__STATIC },
{ "FLAMETHROWERPILOT", DVPTR(FLAMETHROWERPILOT), FLAMETHROWERPILOT__STATIC },
{ "FIREBALL", DVPTR(FIREBALL), FIREBALL__STATIC },
{ "ONFIRE", DVPTR(ONFIRE), ONFIRE__STATIC },
{ "ONFIRESMOKE", DVPTR(ONFIRESMOKE), ONFIRESMOKE__STATIC },
{ "BURNEDCORPSE", DVPTR(BURNEDCORPSE), BURNEDCORPSE__STATIC },
{ "WHISPYSMOKE", DVPTR(WHISPYSMOKE), WHISPYSMOKE__STATIC },
{ "FIREFLY", DVPTR(FIREFLY), FIREFLY__STATIC },
{ "FIREFLYSHRINKEFFECT", DVPTR(FIREFLYSHRINKEFFECT), FIREFLYSHRINKEFFECT__STATIC },
{ "FIREFLYGROWEFFECT", DVPTR(FIREFLYGROWEFFECT), FIREFLYGROWEFFECT__STATIC },
{ "FIREFLYFLYINGEFFECT", DVPTR(FIREFLYFLYINGEFFECT), FIREFLYFLYINGEFFECT__STATIC },
{ "BOSS5", DVPTR(BOSS5), BOSS5__STATIC },
{ "BOSS5STAYPUT", DVPTR(BOSS5STAYPUT), BOSS5STAYPUT__STATIC },
{ "LAVAPOOL", DVPTR(LAVAPOOL), LAVAPOOL__STATIC },
{ "LAVASPLASH", DVPTR(LAVASPLASH), LAVASPLASH__STATIC },
{ "LAVAPOOLBUBBLE", DVPTR(LAVAPOOLBUBBLE), LAVAPOOLBUBBLE__STATIC },
{ "BOSS2STAYPUT", DVPTR(BOSS2STAYPUT), BOSS2STAYPUT__STATIC },
{ "BOSS3STAYPUT", DVPTR(BOSS3STAYPUT), BOSS3STAYPUT__STATIC },
{ "E32_TILE5736", DVPTR(E32_TILE5736), E32_TILE5736__STATIC },
{ "E32_TILE5737", DVPTR(E32_TILE5737), E32_TILE5737__STATIC },
{ "E32_TILE5846", DVPTR(E32_TILE5846), E32_TILE5846__STATIC },
}; };
@ -1239,6 +1271,38 @@ int32_t WINDOWBORDER2 = WINDOWBORDER2__STATIC;
int32_t WOMAN = WOMAN__STATIC; int32_t WOMAN = WOMAN__STATIC;
int32_t WOODENHORSE = WOODENHORSE__STATIC; int32_t WOODENHORSE = WOODENHORSE__STATIC;
int32_t XXXSTACY = XXXSTACY__STATIC; int32_t XXXSTACY = XXXSTACY__STATIC;
int32_t WIDESCREENSTATUSBAR = WIDESCREENSTATUSBAR__STATIC;
int32_t RPGGUNWIDE = RPGGUNWIDE__STATIC;
int32_t FIRSTGUNRELOADWIDE = FIRSTGUNRELOADWIDE__STATIC;
int32_t FREEZEWIDE = FREEZEWIDE__STATIC;
int32_t FREEZEFIREWIDE = FREEZEFIREWIDE__STATIC;
int32_t SHRINKERWIDE = SHRINKERWIDE__STATIC;
int32_t CRACKKNUCKLESWIDE = CRACKKNUCKLESWIDE__STATIC;
int32_t FLAMETHROWERSPRITE = FLAMETHROWERSPRITE__STATIC;
int32_t FLAMETHROWERAMMO = FLAMETHROWERAMMO__STATIC;
int32_t FLAMETHROWER = FLAMETHROWER__STATIC;
int32_t FLAMETHROWERFIRE = FLAMETHROWERFIRE__STATIC;
int32_t FLAMETHROWERFLAME = FLAMETHROWERFLAME__STATIC;
int32_t FLAMETHROWERPILOT = FLAMETHROWERPILOT__STATIC;
int32_t FIREBALL = FIREBALL__STATIC;
int32_t ONFIRE = ONFIRE__STATIC;
int32_t ONFIRESMOKE = ONFIRESMOKE__STATIC;
int32_t BURNEDCORPSE = BURNEDCORPSE__STATIC;
int32_t WHISPYSMOKE = WHISPYSMOKE__STATIC;
int32_t FIREFLY = FIREFLY__STATIC;
int32_t FIREFLYSHRINKEFFECT = FIREFLYSHRINKEFFECT__STATIC;
int32_t FIREFLYGROWEFFECT = FIREFLYGROWEFFECT__STATIC;
int32_t FIREFLYFLYINGEFFECT = FIREFLYFLYINGEFFECT__STATIC;
int32_t BOSS5 = BOSS5__STATIC;
int32_t BOSS5STAYPUT = BOSS5STAYPUT__STATIC;
int32_t LAVAPOOL = LAVAPOOL__STATIC;
int32_t LAVASPLASH = LAVASPLASH__STATIC;
int32_t LAVAPOOLBUBBLE = LAVAPOOLBUBBLE__STATIC;
int32_t BOSS2STAYPUT = BOSS2STAYPUT__STATIC;
int32_t BOSS3STAYPUT = BOSS3STAYPUT__STATIC;
int32_t E32_TILE5736 = E32_TILE5736__STATIC;
int32_t E32_TILE5737 = E32_TILE5737__STATIC;
int32_t E32_TILE5846 = E32_TILE5846__STATIC;
static hashtable_t h_names = {512, NULL}; static hashtable_t h_names = {512, NULL};
@ -1309,5 +1373,8 @@ void G_InitDynamicTiles(void)
WeaponPickupSprites[9] = FREEZESPRITE; WeaponPickupSprites[9] = FREEZESPRITE;
WeaponPickupSprites[10] = HEAVYHBOMB; WeaponPickupSprites[10] = HEAVYHBOMB;
WeaponPickupSprites[11] = SHRINKERSPRITE; WeaponPickupSprites[11] = SHRINKERSPRITE;
WeaponPickupSprites[12] = FLAMETHROWERSPRITE;
#endif
} }
END_DUKE_NS END_DUKE_NS

View file

@ -622,6 +622,38 @@ BEGIN_DUKE_NS
#define SIGN1__STATIC 4909 #define SIGN1__STATIC 4909
#define SIGN2__STATIC 4912 #define SIGN2__STATIC 4912
#define JURYGUY__STATIC 4943 #define JURYGUY__STATIC 4943
#define WIDESCREENSTATUSBAR__STATIC 5120
#define RPGGUNWIDE__STATIC 5121
#define FIRSTGUNRELOADWIDE__STATIC 5122
#define FREEZEWIDE__STATIC 5123
#define FREEZEFIREWIDE__STATIC 5124
#define SHRINKERWIDE__STATIC 5127
#define CRACKKNUCKLESWIDE__STATIC 5129
#define FLAMETHROWERSPRITE__STATIC 5134
#define FLAMETHROWERAMMO__STATIC 5135
#define FLAMETHROWER__STATIC 5138
#define FLAMETHROWERFIRE__STATIC 5139
#define FLAMETHROWERFLAME__STATIC 1891
#define FLAMETHROWERPILOT__STATIC 5174
#define FIREBALL__STATIC 5163
#define ONFIRE__STATIC 5152
#define ONFIRESMOKE__STATIC 5143
#define BURNEDCORPSE__STATIC 5173
#define WHISPYSMOKE__STATIC 5268
#define FIREFLY__STATIC 5180
#define FIREFLYSHRINKEFFECT__STATIC 5360
#define FIREFLYGROWEFFECT__STATIC 5367
#define FIREFLYFLYINGEFFECT__STATIC 5296
#define BOSS5__STATIC 5310
#define BOSS5STAYPUT__STATIC 5311
#define LAVAPOOL__STATIC 5304
#define LAVASPLASH__STATIC 5371
#define LAVAPOOLBUBBLE__STATIC 5207
#define BOSS2STAYPUT__STATIC 2711
#define BOSS3STAYPUT__STATIC 2761
#define E32_TILE5736__STATIC 5736
#define E32_TILE5737__STATIC 5737
#define E32_TILE5846__STATIC 5846
extern int16_t DynamicTileMap[MAXTILES]; extern int16_t DynamicTileMap[MAXTILES];
@ -1230,6 +1262,38 @@ extern int32_t WINDOWBORDER2;
extern int32_t WOMAN; extern int32_t WOMAN;
extern int32_t WOODENHORSE; extern int32_t WOODENHORSE;
extern int32_t XXXSTACY; extern int32_t XXXSTACY;
extern int32_t WIDESCREENSTATUSBAR;
extern int32_t RPGGUNWIDE;
extern int32_t FIRSTGUNRELOADWIDE;
extern int32_t FREEZEWIDE;
extern int32_t FREEZEFIREWIDE;
extern int32_t SHRINKERWIDE;
extern int32_t CRACKKNUCKLESWIDE;
extern int32_t FLAMETHROWERSPRITE;
extern int32_t FLAMETHROWERAMMO;
extern int32_t FLAMETHROWER;
extern int32_t FLAMETHROWERFIRE;
extern int32_t FLAMETHROWERFLAME;
extern int32_t FLAMETHROWERPILOT;
extern int32_t FIREBALL;
extern int32_t ONFIRE;
extern int32_t ONFIRESMOKE;
extern int32_t BURNEDCORPSE;
extern int32_t WHISPYSMOKE;
extern int32_t FIREFLY;
extern int32_t FIREFLYSHRINKEFFECT;
extern int32_t FIREFLYGROWEFFECT;
extern int32_t FIREFLYFLYINGEFFECT;
extern int32_t BOSS5;
extern int32_t BOSS5STAYPUT;
extern int32_t LAVAPOOL;
extern int32_t LAVASPLASH;
extern int32_t LAVAPOOLBUBBLE;
extern int32_t BOSS2STAYPUT;
extern int32_t BOSS3STAYPUT;
extern int32_t E32_TILE5736;
extern int32_t E32_TILE5737;
extern int32_t E32_TILE5846;
#define DYNAMICTILEMAP(Tilenum) (DynamicTileMap[Tilenum]) #define DYNAMICTILEMAP(Tilenum) (DynamicTileMap[Tilenum])

View file

@ -1256,6 +1256,10 @@ static int32_t A_ShootHardcoded(int spriteNum, int projecTile, int shootAng, vec
} }
break; break;
case FIREBALL__STATIC:
if (!WORLDTOUR)
break;
fallthrough__;
case FIRELASER__STATIC: case FIRELASER__STATIC:
case SPIT__STATIC: case SPIT__STATIC:
case COOLEXPLOSION1__STATIC: case COOLEXPLOSION1__STATIC:
@ -1270,6 +1274,14 @@ static int32_t A_ShootHardcoded(int spriteNum, int projecTile, int shootAng, vec
vel = (pSprite->picnum == BOSS2) ? 644 : 348; vel = (pSprite->picnum == BOSS2) ? 644 : 348;
startPos.z -= (4 << 7); startPos.z -= (4 << 7);
break; break;
case FIREBALL__STATIC:
if (pSprite->picnum == BOSS5 || pSprite->picnum == BOSS5STAYPUT)
{
vel = 968;
startPos.z += 0x1800;
break;
}
fallthrough__;
case FIRELASER__STATIC: case FIRELASER__STATIC:
default: default:
vel = 840; vel = 840;
@ -1279,7 +1291,14 @@ static int32_t A_ShootHardcoded(int spriteNum, int projecTile, int shootAng, vec
if (playerNum >= 0) if (playerNum >= 0)
{ {
if (GetAutoAimAng(spriteNum, playerNum, projecTile, -ZOFFSET4, 0, &startPos, vel, &Zvel, &shootAng) < 0) if (projecTile == FIREBALL)
{
Zvel = fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) * 98;
startPos.x += sintable[(348+shootAng+512)&2047]/448;
startPos.y += sintable[(348+shootAng)&2047]/448;
startPos.z += 0x300;
}
else if (GetAutoAimAng(spriteNum, playerNum, projecTile, -ZOFFSET4, 0, &startPos, vel, &Zvel, &shootAng) < 0)
Zvel = fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) * 98; Zvel = fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) * 98;
} }
else else
@ -1318,6 +1337,16 @@ static int32_t A_ShootHardcoded(int spriteNum, int projecTile, int shootAng, vec
sprite[returnSprite].ang += 128 - (krand() & 255); sprite[returnSprite].ang += 128 - (krand() & 255);
} }
} }
else if (projecTile == FIREBALL)
{
if (PN(spriteNum) == BOSS5 || PN(spriteNum) == BOSS5STAYPUT || playerNum >= 0)
{
sprite[returnSprite].xrepeat = 40;
sprite[returnSprite].yrepeat = 40;
}
sprite[returnSprite].yvel = playerNum;
//sprite[returnSprite].cstat |= 0x4000;
}
sprite[returnSprite].cstat = 128; sprite[returnSprite].cstat = 128;
sprite[returnSprite].clipdist = 4; sprite[returnSprite].clipdist = 4;
@ -1571,6 +1600,86 @@ static int32_t A_ShootHardcoded(int spriteNum, int projecTile, int shootAng, vec
return returnSprite; return returnSprite;
} }
case FLAMETHROWERFLAME__STATIC:
{
if (!WORLDTOUR)
break;
if (pSprite->extra >= 0) pSprite->shade = -96;
vel = 1024;
int j, underwater;
if (playerNum >= 0)
{
Zvel = fix16_to_int(F16(100) - pPlayer->q16horiz - pPlayer->q16horizoff) * 81;
int xv = sprite[pPlayer->i].xvel;
if (xv)
{
int ang = getangle(startPos.x-pPlayer->opos.x,startPos.y-pPlayer->opos.y);
ang = 512-(1024-klabs(klabs(ang-shootAng)-1024));
vel = 1024+int(float(ang)*(1.f/512.f)*float(xv));
}
underwater = sector[pPlayer->cursectnum].lotag == ST_2_UNDERWATER;
}
else
{
// NOTE: j is a player index
j = A_FindPlayer(pSprite, NULL);
shootAng = getangle(g_player[j].ps->opos.x - startPos.x, g_player[j].ps->opos.y - startPos.y);
if (PN(spriteNum) == BOSS3 || PN(spriteNum) == BOSS3STAYPUT)
startPos.z -= MinibossScale(spriteNum, ZOFFSET5);
else if (PN(spriteNum) == BOSS5 || PN(spriteNum) == BOSS5STAYPUT)
{
vel += 128;
startPos.z += MinibossScale(spriteNum, 24 << 8);
}
Zvel = tabledivide32_noinline((g_player[j].ps->opos.z - startPos.z) * vel, safeldist(g_player[j].ps->i, pSprite));
if (A_CheckEnemySprite(pSprite) && (AC_MOVFLAGS(pSprite, &actor[spriteNum]) & face_player_smart))
shootAng = pSprite->ang + (krand() & 31) - 16;
underwater = sector[pSprite->sectnum].lotag == 2;
}
if (underwater)
{
if ((krand() % 5) != 0)
return -1;
j = A_Spawn(spriteNum, WATERBUBBLE);
}
else
{
j = A_Spawn(spriteNum, projecTile);
sprite[j].zvel = Zvel;
sprite[j].xvel = vel;
}
sprite[j].x = startPos.x+sintable[(shootAng+630)&2047]/448;
sprite[j].y = startPos.y+sintable[(shootAng+112)&2047]/448;
sprite[j].z = startPos.z-0x100;
sprite[j].cstat = 128;
sprite[j].ang = shootAng;
sprite[j].xrepeat = sprite[j].xrepeat = 2;
sprite[j].clipdist = 40;
sprite[j].owner = spriteNum;
sprite[j].yvel = playerNum;
if (playerNum == -1 && (sprite[spriteNum].picnum == BOSS5 || sprite[spriteNum].picnum == BOSS5))
{
sprite[j].xrepeat = sprite[j].yrepeat = 10;
sprite[j].x -= sintable[shootAng&2047]/56;
sprite[j].y -= sintable[(shootAng-512)&2047]/56;
}
return j;
}
case FIREFLY__STATIC:
{
if (!WORLDTOUR)
break;
int j = A_Spawn(spriteNum, projecTile);
sprite[j].pos = startPos;
sprite[j].ang = shootAng;
sprite[j].xvel = 500;
sprite[j].zvel = 0;
return j;
}
} }
return -1; return -1;
@ -1953,6 +2062,9 @@ static void P_FireWeapon(int playerNum)
if (PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) != KNEE_WEAPON) if (PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) != KNEE_WEAPON)
pPlayer->ammo_amount[pPlayer->curr_weapon]--; pPlayer->ammo_amount[pPlayer->curr_weapon]--;
if (PWEAPON(playerNum, pPlayer->curr_weapon, WorksLike) == FLAMETHROWER_WEAPON && sector[pPlayer->cursectnum].lotag == ST_2_UNDERWATER)
return;
if (PWEAPON(playerNum, pPlayer->curr_weapon, FireSound) > 0) if (PWEAPON(playerNum, pPlayer->curr_weapon, FireSound) > 0)
A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, FireSound), pPlayer->i); A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, FireSound), pPlayer->i);
@ -2785,6 +2897,31 @@ void P_DisplayWeapon(void)
FREEZE, weaponShade, weaponBits, weaponPal); FREEZE, weaponShade, weaponBits, weaponPal);
break; break;
case FLAMETHROWER_WEAPON:
if ((*weaponFrame) < (PWEAPON(screenpeek, pPlayer->curr_weapon, TotalTime) + 1) && (*weaponFrame) >= 1 && sector[pPlayer->cursectnum].lotag != ST_2_UNDERWATER)
{
static uint8_t freezerFrames[] = { 0, 0, 1, 1, 2, 2 };
if (doAnim)
{
weaponX += rand() & 1;
weaponY += rand() & 1;
}
weaponYOffset -= 16;
G_DrawWeaponTileWithID(currentWeapon << 1, weaponX + 210 - (pPlayer->look_ang >> 1), weaponY + 261 - weaponYOffset,
FLAMETHROWERFIRE, -32, weaponBits, weaponPal);
G_DrawWeaponTileWithID(currentWeapon, weaponX + 210 - (pPlayer->look_ang >> 1), weaponY + 235 - weaponYOffset,
FLAMETHROWERFIRE + 1 + freezerFrames[*weaponFrame % 6], -32, weaponBits, weaponPal);
}
else
{
G_DrawWeaponTileWithID(currentWeapon, weaponX + 210 - (pPlayer->look_ang >> 1), weaponY + 261 - weaponYOffset,
FLAMETHROWER, weaponShade, weaponBits, weaponPal);
G_DrawWeaponTileWithID(currentWeapon, weaponX + 210 - (pPlayer->look_ang >> 1), weaponY + 261 - weaponYOffset,
FLAMETHROWERPILOT, weaponShade, weaponBits, weaponPal);
}
break;
case GROW_WEAPON: case GROW_WEAPON:
case SHRINKER_WEAPON: case SHRINKER_WEAPON:
weaponX += 28; weaponX += 28;
@ -3431,7 +3568,7 @@ access_incs:
int16_t WeaponPickupSprites[MAX_WEAPONS] = { KNEE__STATIC, FIRSTGUNSPRITE__STATIC, SHOTGUNSPRITE__STATIC, int16_t WeaponPickupSprites[MAX_WEAPONS] = { KNEE__STATIC, FIRSTGUNSPRITE__STATIC, SHOTGUNSPRITE__STATIC,
CHAINGUNSPRITE__STATIC, RPGSPRITE__STATIC, HEAVYHBOMB__STATIC, SHRINKERSPRITE__STATIC, DEVISTATORSPRITE__STATIC, CHAINGUNSPRITE__STATIC, RPGSPRITE__STATIC, HEAVYHBOMB__STATIC, SHRINKERSPRITE__STATIC, DEVISTATORSPRITE__STATIC,
TRIPBOMBSPRITE__STATIC, FREEZESPRITE__STATIC, HEAVYHBOMB__STATIC, SHRINKERSPRITE__STATIC TRIPBOMBSPRITE__STATIC, FREEZESPRITE__STATIC, HEAVYHBOMB__STATIC, SHRINKERSPRITE__STATIC, FLAMETHROWERSPRITE__STATIC
}; };
// this is used for player deaths // this is used for player deaths
void P_DropWeapon(int const playerNum) void P_DropWeapon(int const playerNum)
@ -4157,6 +4294,15 @@ static void P_ProcessWeapon(int playerNum)
} }
break; break;
case FLAMETHROWER_WEAPON:
if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0)
{
(*weaponFrame) = 1;
if (PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound) > 0 && sector[pPlayer->cursectnum].lotag != ST_2_UNDERWATER)
A_PlaySound(PWEAPON(playerNum, pPlayer->curr_weapon, InitialSound), pPlayer->i);
}
break;
case DEVISTATOR_WEAPON: case DEVISTATOR_WEAPON:
if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0) if (pPlayer->ammo_amount[pPlayer->curr_weapon] > 0)
{ {

View file

@ -219,7 +219,7 @@ typedef struct {
#endif #endif
int8_t crouch_toggle; int8_t crouch_toggle;
int8_t padding_[1]; int8_t padding_[3];
} DukePlayer_t; } DukePlayer_t;
// KEEPINSYNC lunatic/_defs_game.lua // KEEPINSYNC lunatic/_defs_game.lua

View file

@ -614,7 +614,7 @@ void G_DrawStatusBar(int32_t snum)
int32_t asprites[MAX_WEAPONS] = { -1, AMMO, SHOTGUNAMMO, BATTERYAMMO, int32_t asprites[MAX_WEAPONS] = { -1, AMMO, SHOTGUNAMMO, BATTERYAMMO,
RPGAMMO, HBOMBAMMO, CRYSTALAMMO, DEVISTATORAMMO, RPGAMMO, HBOMBAMMO, CRYSTALAMMO, DEVISTATORAMMO,
TRIPBOMBSPRITE, FREEZEAMMO+1, HBOMBAMMO, GROWAMMO TRIPBOMBSPRITE, FREEZEAMMO+1, HBOMBAMMO, GROWAMMO, FLAMETHROWERAMMO+1,
}; };
Bmemcpy(ammo_sprites, asprites, sizeof(ammo_sprites)); Bmemcpy(ammo_sprites, asprites, sizeof(ammo_sprites));
} }

View file

@ -1999,6 +1999,11 @@ void A_DamageObject_Duke3D(int spriteNum, int const dmgSrc)
{ {
switch (DYNAMICTILEMAP(sprite[dmgSrc].picnum)) switch (DYNAMICTILEMAP(sprite[dmgSrc].picnum))
{ {
case FLAMETHROWERFLAME__STATIC:
case FIREBALL__STATIC:
if (!WORLDTOUR)
break;
fallthrough__;
case RADIUSEXPLOSION__STATIC: case RADIUSEXPLOSION__STATIC:
case RPG__STATIC: case RPG__STATIC:
case FIRELASER__STATIC: case FIRELASER__STATIC:
@ -2142,6 +2147,15 @@ void A_DamageObject_Duke3D(int spriteNum, int const dmgSrc)
A_DeleteSprite(spriteNum); A_DeleteSprite(spriteNum);
return; return;
case E32_TILE5736__STATIC:
case E32_TILE5737__STATIC:
if (!WORLDTOUR)
break;
A_PlaySound(GLASS_BREAKING,spriteNum);
A_SpawnWallGlass(spriteNum,-1,10);
A_DeleteSprite(spriteNum);
return;
case HYDROPLANT__STATIC: case HYDROPLANT__STATIC:
PN(spriteNum) = BROKEHYDROPLANT; PN(spriteNum) = BROKEHYDROPLANT;
A_PlaySound(GLASS_BREAKING,spriteNum); A_PlaySound(GLASS_BREAKING,spriteNum);
@ -2250,6 +2264,10 @@ void A_DamageObject_Duke3D(int spriteNum, int const dmgSrc)
A_PlaySound(SLT(spriteNum),spriteNum); A_PlaySound(SLT(spriteNum),spriteNum);
A_Spawn(spriteNum,SHT(spriteNum)); A_Spawn(spriteNum,SHT(spriteNum));
fallthrough__; fallthrough__;
case E32_TILE5846__STATIC:
if (!WORLDTOUR && PN(spriteNum) == E32_TILE5846)
break;
fallthrough__;
case SPACEMARINE__STATIC: case SPACEMARINE__STATIC:
sprite[spriteNum].extra -= sprite[dmgSrc].extra; sprite[spriteNum].extra -= sprite[dmgSrc].extra;
if (sprite[spriteNum].extra > 0) if (sprite[spriteNum].extra > 0)
@ -2321,6 +2339,9 @@ void A_DamageObject_Duke3D(int spriteNum, int const dmgSrc)
{ {
if (A_CheckEnemySprite(&sprite[spriteNum]) == 1) if (A_CheckEnemySprite(&sprite[spriteNum]) == 1)
{ {
if (WORLDTOUR && sprite[spriteNum].picnum == FIREFLY && sprite[spriteNum].xrepeat < 48)
return;
if (sprite[dmgSrc].picnum == RPG) if (sprite[dmgSrc].picnum == RPG)
sprite[dmgSrc].extra <<= 1; sprite[dmgSrc].extra <<= 1;
@ -2378,7 +2399,11 @@ void A_DamageObject_Duke3D(int spriteNum, int const dmgSrc)
if (sprite[dmgSrc].picnum == FREEZEBLAST && ((PN(spriteNum) == APLAYER && sprite[spriteNum].pal == 1) || (g_freezerSelfDamage == 0 && sprite[dmgSrc].owner == spriteNum))) if (sprite[dmgSrc].picnum == FREEZEBLAST && ((PN(spriteNum) == APLAYER && sprite[spriteNum].pal == 1) || (g_freezerSelfDamage == 0 && sprite[dmgSrc].owner == spriteNum)))
return; return;
actor[spriteNum].picnum = sprite[dmgSrc].picnum; if (WORLDTOUR && sprite[dmgSrc].picnum == FIREBALL && sprite[sprite[spriteNum].owner].picnum != FIREBALL)
actor[spriteNum].picnum = FLAMETHROWERFLAME;
else
actor[spriteNum].picnum = sprite[dmgSrc].picnum;
actor[spriteNum].extra += sprite[dmgSrc].extra; actor[spriteNum].extra += sprite[dmgSrc].extra;
actor[spriteNum].ang = sprite[dmgSrc].ang; actor[spriteNum].ang = sprite[dmgSrc].ang;
actor[spriteNum].owner = sprite[dmgSrc].owner; actor[spriteNum].owner = sprite[dmgSrc].owner;
@ -2785,6 +2810,8 @@ CHECKINV1:
{ {
// if( ( p->weapon_pos == 0 || ( p->holster_weapon && p->weapon_pos == WEAPON_POS_LOWER ) )) // if( ( p->weapon_pos == 0 || ( p->holster_weapon && p->weapon_pos == WEAPON_POS_LOWER ) ))
{ {
if (weaponNum >= 12) // hack
weaponNum++;
if (weaponNum == 10 || weaponNum == 11) if (weaponNum == 10 || weaponNum == 11)
{ {
int currentWeapon = pPlayer->curr_weapon; int currentWeapon = pPlayer->curr_weapon;
@ -2792,7 +2819,7 @@ CHECKINV1:
weaponNum = (weaponNum == 10 ? -1 : 1); // JBF: prev (-1) or next (1) weapon choice weaponNum = (weaponNum == 10 ? -1 : 1); // JBF: prev (-1) or next (1) weapon choice
int i = currentWeapon; int i = currentWeapon;
while ((currentWeapon >= 0 && currentWeapon < 11) || (PLUTOPAK && currentWeapon == GROW_WEAPON)) while ((currentWeapon >= 0 && currentWeapon < 11) || (PLUTOPAK && currentWeapon == GROW_WEAPON) || (WORLDTOUR && currentWeapon == FLAMETHROWER_WEAPON))
{ {
// this accounts for the expander when handling next/previous // this accounts for the expander when handling next/previous
@ -2826,6 +2853,34 @@ CHECKINV1:
currentWeapon--; currentWeapon--;
break; break;
case KNEE_WEAPON:
if ((int32_t) weaponNum == -1)
{
if (WORLDTOUR)
currentWeapon = FLAMETHROWER_WEAPON;
else
currentWeapon = FREEZE_WEAPON;
}
else
currentWeapon++;
break;
case FLAMETHROWER_WEAPON:
currentWeapon = ((int32_t) weaponNum == -1) ? FREEZE_WEAPON : KNEE_WEAPON;
break;
case FREEZE_WEAPON:
if ((int32_t)weaponNum == 1)
{
if (WORLDTOUR)
currentWeapon = FLAMETHROWER_WEAPON;
else
currentWeapon = KNEE_WEAPON;
}
else
currentWeapon--;
break;
case HANDREMOTE_WEAPON: case HANDREMOTE_WEAPON:
i = currentWeapon = HANDBOMB_WEAPON; i = currentWeapon = HANDBOMB_WEAPON;
fallthrough__; fallthrough__;
@ -2834,9 +2889,6 @@ CHECKINV1:
break; break;
} }
if (currentWeapon == -1) currentWeapon = FREEZE_WEAPON;
else if (currentWeapon == 10) currentWeapon = KNEE_WEAPON;
if (((pPlayer->gotweapon & (1<<currentWeapon)) && pPlayer->ammo_amount[currentWeapon] > 0) || P_CheckDetonatorSpecialCase(pPlayer, currentWeapon)) if (((pPlayer->gotweapon & (1<<currentWeapon)) && pPlayer->ammo_amount[currentWeapon] > 0) || P_CheckDetonatorSpecialCase(pPlayer, currentWeapon))
{ {
weaponNum = currentWeapon; weaponNum = currentWeapon;
@ -2854,12 +2906,16 @@ CHECKINV1:
pPlayer->subweapon &= ~(1 << GROW_WEAPON); pPlayer->subweapon &= ~(1 << GROW_WEAPON);
else if (weaponNum == GROW_WEAPON) else if (weaponNum == GROW_WEAPON)
pPlayer->subweapon |= (1<<GROW_WEAPON); pPlayer->subweapon |= (1<<GROW_WEAPON);
else if (weaponNum == FREEZE_WEAPON)
pPlayer->subweapon &= ~(1 << FLAMETHROWER_WEAPON);
else if (weaponNum == FLAMETHROWER_WEAPON)
pPlayer->subweapon |= (1<<FLAMETHROWER_WEAPON);
} }
// last used weapon will depend on subweapon // last used weapon will depend on subweapon
if (weaponNum >= 12) // alt weapon, last used weapon if (weaponNum >= 13) // alt weapon, last used weapon
{ {
uint32_t const weaponNumSwitch = weaponNum == 13 ? pPlayer->last_used_weapon : pPlayer->curr_weapon; uint32_t const weaponNumSwitch = weaponNum == 14 ? pPlayer->last_used_weapon : pPlayer->curr_weapon;
switch (weaponNumSwitch) switch (weaponNumSwitch)
{ {
case HANDREMOTE_WEAPON: case HANDREMOTE_WEAPON:
@ -2868,6 +2924,9 @@ CHECKINV1:
case GROW_WEAPON: case GROW_WEAPON:
weaponNum = SHRINKER_WEAPON; weaponNum = SHRINKER_WEAPON;
break; break;
case FLAMETHROWER_WEAPON:
weaponNum = FREEZE_WEAPON;
break;
default: default:
weaponNum = weaponNumSwitch; weaponNum = weaponNumSwitch;
break; break;
@ -2915,6 +2974,34 @@ CHECKINV1:
pPlayer->subweapon &= ~(1<<GROW_WEAPON); pPlayer->subweapon &= ~(1<<GROW_WEAPON);
} }
if (weaponNum == FREEZE_WEAPON && WORLDTOUR)
{
if (screenpeek == playerNum) pus = NUMPAGES;
if (pPlayer->curr_weapon != FLAMETHROWER_WEAPON && pPlayer->curr_weapon != FREEZE_WEAPON)
{
if (pPlayer->ammo_amount[FLAMETHROWER_WEAPON] > 0)
{
if ((pPlayer->subweapon&(1<<FLAMETHROWER_WEAPON)) == (1<<FLAMETHROWER_WEAPON))
weaponNum = FLAMETHROWER_WEAPON;
else if (pPlayer->ammo_amount[FREEZE_WEAPON] == 0)
{
weaponNum = FLAMETHROWER_WEAPON;
pPlayer->subweapon |= (1<<FLAMETHROWER_WEAPON);
}
}
else if (pPlayer->ammo_amount[FREEZE_WEAPON] > 0)
pPlayer->subweapon &= ~(1<<FLAMETHROWER_WEAPON);
}
else if (pPlayer->curr_weapon == FREEZE_WEAPON)
{
pPlayer->subweapon |= (1<<FLAMETHROWER_WEAPON);
weaponNum = FLAMETHROWER_WEAPON;
}
else
pPlayer->subweapon &= ~(1<<FLAMETHROWER_WEAPON);
}
if (pPlayer->holster_weapon) if (pPlayer->holster_weapon)
{ {
playerBits |= BIT(SK_HOLSTER); playerBits |= BIT(SK_HOLSTER);
@ -2931,6 +3018,7 @@ CHECKINV1:
case FREEZE_WEAPON: case FREEZE_WEAPON:
case GROW_WEAPON: case GROW_WEAPON:
case SHRINKER_WEAPON: case SHRINKER_WEAPON:
case FLAMETHROWER_WEAPON:
if (pPlayer->ammo_amount[weaponNum] == 0 && pPlayer->show_empty_weapon == 0) if (pPlayer->ammo_amount[weaponNum] == 0 && pPlayer->show_empty_weapon == 0)
{ {
pPlayer->last_full_weapon = pPlayer->curr_weapon; pPlayer->last_full_weapon = pPlayer->curr_weapon;

View file

@ -187,6 +187,9 @@ LUNATIC_EXTERN struct dynitem g_dynSoundList[] =
{ "WIERDSHOT_FLY", DVPTR(WIERDSHOT_FLY), WIERDSHOT_FLY__STATIC }, { "WIERDSHOT_FLY", DVPTR(WIERDSHOT_FLY), WIERDSHOT_FLY__STATIC },
{ "WIND_AMBIENCE", DVPTR(WIND_AMBIENCE), WIND_AMBIENCE__STATIC }, { "WIND_AMBIENCE", DVPTR(WIND_AMBIENCE), WIND_AMBIENCE__STATIC },
{ "WIND_REPEAT", DVPTR(WIND_REPEAT), WIND_REPEAT__STATIC }, { "WIND_REPEAT", DVPTR(WIND_REPEAT), WIND_REPEAT__STATIC },
{ "FLAMETHROWER_INTRO", DVPTR(FLAMETHROWER_INTRO), FLAMETHROWER_INTRO__STATIC },
{ "FLAMETHROWER_LOOP", DVPTR(FLAMETHROWER_LOOP), FLAMETHROWER_LOOP__STATIC },
{ "FLAMETHROWER_END", DVPTR(FLAMETHROWER_END), FLAMETHROWER_END__STATIC },
}; };
#ifdef DYNSOUNDREMAP_ENABLE #ifdef DYNSOUNDREMAP_ENABLE
@ -329,6 +332,9 @@ int32_t WHIPYOURASS = WHIPYOURASS__STATIC;
int32_t WIERDSHOT_FLY = WIERDSHOT_FLY__STATIC; int32_t WIERDSHOT_FLY = WIERDSHOT_FLY__STATIC;
int32_t WIND_AMBIENCE = WIND_AMBIENCE__STATIC; int32_t WIND_AMBIENCE = WIND_AMBIENCE__STATIC;
int32_t WIND_REPEAT = WIND_REPEAT__STATIC; int32_t WIND_REPEAT = WIND_REPEAT__STATIC;
int32_t FLAMETHROWER_INTRO = FLAMETHROWER_INTRO__STATIC;
int32_t FLAMETHROWER_LOOP = FLAMETHROWER_LOOP__STATIC;
int32_t FLAMETHROWER_END = FLAMETHROWER_END__STATIC;
#if !defined LUNATIC #if !defined LUNATIC
static hashtable_t h_names = {512, NULL}; static hashtable_t h_names = {512, NULL};

View file

@ -165,6 +165,9 @@ BEGIN_DUKE_NS
#define EXPANDERSHOOT__STATIC 388 #define EXPANDERSHOOT__STATIC 388
#define INTRO4_B__STATIC 392 #define INTRO4_B__STATIC 392
#define BIGBANG__STATIC 393 #define BIGBANG__STATIC 393
#define FLAMETHROWER_INTRO__STATIC 398
#define FLAMETHROWER_LOOP__STATIC 399
#define FLAMETHROWER_END__STATIC 400
extern int16_t DynamicSoundMap[MAXSOUNDS]; extern int16_t DynamicSoundMap[MAXSOUNDS];
@ -317,6 +320,9 @@ extern int32_t WHIPYOURASS;
extern int32_t WIERDSHOT_FLY; extern int32_t WIERDSHOT_FLY;
extern int32_t WIND_AMBIENCE; extern int32_t WIND_AMBIENCE;
extern int32_t WIND_REPEAT; extern int32_t WIND_REPEAT;
extern int32_t FLAMETHROWER_INTRO;
extern int32_t FLAMETHROWER_LOOP;
extern int32_t FLAMETHROWER_END;
#define DYNAMICSOUNDMAP(Soundnum) (DynamicSoundMap[Soundnum]) #define DYNAMICSOUNDMAP(Soundnum) (DynamicSoundMap[Soundnum])