Merge branch 'new-acz-minecarts' into 'master'

ACZ hardcoding (including minecarts)

See merge request STJr/SRB2Internal!231
This commit is contained in:
MascaraSnake 2019-06-21 17:45:03 -04:00
commit e20949ef77
13 changed files with 3206 additions and 180 deletions

View File

@ -232,7 +232,8 @@ typedef enum
// Specific level gimmicks.
CR_ZOOMTUBE,
CR_ROPEHANG,
CR_MACESPIN
CR_MACESPIN,
CR_MINECART
} carrytype_t; // pw_carry
// Player powers. (don't edit this comment)

View File

@ -2265,6 +2265,9 @@ static actionpointer_t actionpointers[] =
{{A_CrushclawLaunch}, "A_CRUSHCLAWLAUNCH"},
{{A_VultureVtol}, "A_VULTUREVTOL"},
{{A_VultureCheck}, "A_VULTURECHECK"},
{{A_VultureHover}, "A_VULTUREHOVER"},
{{A_VultureBlast}, "A_VULTUREBLAST"},
{{A_VultureFly}, "A_VULTUREFLY"},
{{A_SkimChase}, "A_SKIMCHASE"},
{{A_1upThinker}, "A_1UPTHINKER"},
{{A_SkullAttack}, "A_SKULLATTACK"},
@ -2393,8 +2396,18 @@ static actionpointer_t actionpointers[] =
{{A_Boss5MakeItRain}, "A_BOSS5MAKEITRAIN"},
{{A_LookForBetter}, "A_LOOKFORBETTER"},
{{A_Boss5BombExplode}, "A_BOSS5BOMBEXPLODE"},
{{NULL}, "NONE"},
{{A_DustDevilThink}, "A_DUSTDEVILTHINK"},
{{A_TNTExplode}, "A_TNTEXPLODE"},
{{A_DebrisRandom}, "A_DEBRISRANDOM"},
{{A_TrainCameo}, "A_TRAINCAMEO"},
{{A_TrainCameo2}, "A_TRAINCAMEO2"},
{{A_CanarivoreGas}, "A_CANARIVOREGAS"},
{{A_KillSegments}, "A_KILLSEGMENTS"},
{{A_SnapperSpawn}, "A_SNAPPERSPAWN"},
{{A_SnapperThinker}, "A_SNAPPERTHINKER"},
{{A_SaloonDoorSpawn}, "A_SALOONDOORSPAWN"},
{{A_MinecartSparkThink}, "A_MINECARTSPARKTHINK"},
{{NULL}, "NONE"},
// This NULL entry must be the last in the list
{{NULL}, NULL},
@ -4381,15 +4394,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Vulture
"S_VULTURE_STND",
"S_VULTURE_VTOL1",
"S_VULTURE_VTOL2",
"S_VULTURE_VTOL3",
"S_VULTURE_VTOL4",
"S_VULTURE_DRIFT",
"S_VULTURE_ZOOM1",
"S_VULTURE_ZOOM2",
"S_VULTURE_ZOOM3",
"S_VULTURE_ZOOM4",
"S_VULTURE_ZOOM5",
"S_VULTURE_STUNNED",
// Pointy
"S_POINTY1",
@ -4440,15 +4448,31 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_EGGSHIELDBREAK",
// Green Snapper
"S_SNAPPER_SPAWN",
"S_SNAPPER_SPAWN2",
"S_GSNAPPER_STND",
"S_GSNAPPER1",
"S_GSNAPPER2",
"S_GSNAPPER3",
"S_GSNAPPER4",
"S_SNAPPER_XPLD",
"S_SNAPPER_LEG",
"S_SNAPPER_LEGRAISE",
"S_SNAPPER_HEAD",
// Minus
"S_MINUS_INIT",
"S_MINUS_STND",
"S_MINUS_DIGGING",
"S_MINUS_DIGGING1",
"S_MINUS_DIGGING2",
"S_MINUS_DIGGING3",
"S_MINUS_DIGGING4",
"S_MINUS_BURST0",
"S_MINUS_BURST1",
"S_MINUS_BURST2",
"S_MINUS_BURST3",
"S_MINUS_BURST4",
"S_MINUS_BURST5",
"S_MINUS_POPUP",
"S_MINUS_UPWARD1",
"S_MINUS_UPWARD2",
@ -4467,6 +4491,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_MINUS_DOWNWARD7",
"S_MINUS_DOWNWARD8",
// Minus dirt
"S_MINUSDIRT1",
"S_MINUSDIRT2",
"S_MINUSDIRT3",
"S_MINUSDIRT4",
"S_MINUSDIRT5",
"S_MINUSDIRT6",
"S_MINUSDIRT7",
// Spring Shell
"S_SSHELL_STND",
"S_SSHELL_RUN1",
@ -4494,6 +4527,28 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_UNIDUS_RUN",
"S_UNIDUS_BALL",
// Canarivore
"S_CANARIVORE_LOOK",
"S_CANARIVORE_AWAKEN1",
"S_CANARIVORE_AWAKEN2",
"S_CANARIVORE_AWAKEN3",
"S_CANARIVORE_GAS1",
"S_CANARIVORE_GAS2",
"S_CANARIVORE_GAS3",
"S_CANARIVORE_GAS4",
"S_CANARIVORE_GAS5",
"S_CANARIVORE_GASREPEAT",
"S_CANARIVORE_CLOSE1",
"S_CANARIVORE_CLOSE2",
"S_CANARIVOREGAS_1",
"S_CANARIVOREGAS_2",
"S_CANARIVOREGAS_3",
"S_CANARIVOREGAS_4",
"S_CANARIVOREGAS_5",
"S_CANARIVOREGAS_6",
"S_CANARIVOREGAS_7",
"S_CANARIVOREGAS_8",
// Boss Explosion
"S_BOSSEXPLODE",
@ -5681,6 +5736,85 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_ARIDSIGN_CACTI",
"S_ARIDSIGN_SHARPTURN",
// Oil lamp
"S_OILLAMP",
"S_OILLAMPFLARE",
// TNT barrel
"S_TNTBARREL_STND1",
"S_TNTBARREL_EXPL1",
"S_TNTBARREL_EXPL2",
"S_TNTBARREL_EXPL3",
"S_TNTBARREL_EXPL4",
"S_TNTBARREL_EXPL5",
"S_TNTBARREL_EXPL6",
"S_TNTBARREL_FLYING",
// TNT proximity shell
"S_PROXIMITY_TNT",
"S_PROXIMITY_TNT_TRIGGER1",
"S_PROXIMITY_TNT_TRIGGER2",
"S_PROXIMITY_TNT_TRIGGER3",
"S_PROXIMITY_TNT_TRIGGER4",
"S_PROXIMITY_TNT_TRIGGER5",
"S_PROXIMITY_TNT_TRIGGER6",
"S_PROXIMITY_TNT_TRIGGER7",
"S_PROXIMITY_TNT_TRIGGER8",
"S_PROXIMITY_TNT_TRIGGER9",
"S_PROXIMITY_TNT_TRIGGER10",
"S_PROXIMITY_TNT_TRIGGER11",
"S_PROXIMITY_TNT_TRIGGER12",
"S_PROXIMITY_TNT_TRIGGER13",
"S_PROXIMITY_TNT_TRIGGER14",
"S_PROXIMITY_TNT_TRIGGER15",
"S_PROXIMITY_TNT_TRIGGER16",
"S_PROXIMITY_TNT_TRIGGER17",
"S_PROXIMITY_TNT_TRIGGER18",
"S_PROXIMITY_TNT_TRIGGER19",
"S_PROXIMITY_TNT_TRIGGER20",
"S_PROXIMITY_TNT_TRIGGER21",
"S_PROXIMITY_TNT_TRIGGER22",
"S_PROXIMITY_TNT_TRIGGER23",
// Dust devil
"S_DUSTDEVIL",
"S_DUSTLAYER1",
"S_DUSTLAYER2",
"S_DUSTLAYER3",
"S_DUSTLAYER4",
"S_DUSTLAYER5",
"S_ARIDDUST1",
"S_ARIDDUST2",
"S_ARIDDUST3",
// Minecart
"S_MINECART_IDLE",
"S_MINECART_DTH1",
"S_MINECARTEND",
"S_MINECARTSEG_FRONT",
"S_MINECARTSEG_BACK",
"S_MINECARTSEG_LEFT",
"S_MINECARTSEG_RIGHT",
"S_MINECARTSIDEMARK1",
"S_MINECARTSIDEMARK2",
"S_MINECARTSPARK",
// Saloon door
"S_SALOONDOOR",
"S_SALOONDOORTHINKER",
// Train cameo
"S_TRAINCAMEOSPAWNER_1",
"S_TRAINCAMEOSPAWNER_2",
"S_TRAINCAMEOSPAWNER_3",
"S_TRAINCAMEOSPAWNER_4",
"S_TRAINCAMEOSPAWNER_5",
"S_TRAINPUFFMAKER",
// Train
"S_TRAINDUST",
"S_TRAINSTEAM",
// Flame jet
"S_FLAMEJETSTND",
"S_FLAMEJETSTART",
@ -7003,6 +7137,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_DUST3",
"S_DUST4",
"S_WOODDEBRIS",
"S_ROCKSPAWN",
"S_ROCKCRUMBLEA",
@ -7066,11 +7202,16 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_EGGGUARD", // Egg Guard
"MT_EGGSHIELD", // Egg Guard's shield
"MT_GSNAPPER", // Green Snapper
"MT_SNAPPER_LEG", // Green Snapper leg
"MT_SNAPPER_HEAD", // Green Snapper head
"MT_MINUS", // Minus
"MT_MINUSDIRT", // Minus dirt
"MT_SPRINGSHELL", // Spring Shell
"MT_YELLOWSHELL", // Spring Shell (yellow)
"MT_UNIDUS", // Unidus
"MT_UNIBALL", // Unidus Ball
"MT_CANARIVORE", // Canarivore
"MT_CANARIVORE_GAS", // Canarivore gas
// Generic Boss Items
"MT_BOSSEXPLODE",
@ -7369,6 +7510,26 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_ARIDSIGN_CAUTION",
"MT_ARIDSIGN_CACTI",
"MT_ARIDSIGN_SHARPTURN",
"MT_OILLAMP",
"MT_TNTBARREL",
"MT_PROXIMITYTNT",
"MT_DUSTDEVIL",
"MT_DUSTLAYER",
"MT_ARIDDUST",
"MT_MINECART",
"MT_MINECARTSEG",
"MT_MINECARTSPAWNER",
"MT_MINECARTEND",
"MT_MINECARTENDSOLID",
"MT_MINECARTSIDEMARK",
"MT_MINECARTSPARK",
"MT_SALOONDOOR",
"MT_SALOONDOORTHINKER",
"MT_TRAINCAMEOSPAWNER",
"MT_TRAINSEG",
"MT_TRAINDUSTSPAWNER",
"MT_TRAINSTEAMSPAWNER",
"MT_MINECARTSWITCHPOINT",
// Red Volcano Scenery
"MT_FLAMEJET",
@ -7691,6 +7852,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_EXPLODE", // Robot Explosion
"MT_UWEXPLODE", // Underwater Explosion
"MT_DUST",
"MT_WOODDEBRIS",
"MT_ROCKSPAWNER",
"MT_FALLINGROCK",
"MT_ROCKCRUMBLE1",
@ -8366,6 +8528,7 @@ struct {
{"CR_ZOOMTUBE",CR_ZOOMTUBE},
{"CR_ROPEHANG",CR_ROPEHANG},
{"CR_MACESPIN",CR_MACESPIN},
{"CR_MINECART",CR_MINECART},
// Ring weapons (ringweapons_t)
// Useful for A_GiveWeapon

View File

@ -172,9 +172,14 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_SPSH
&lspr[NOLIGHT], // SPR_ESHI
&lspr[NOLIGHT], // SPR_GSNP
&lspr[NOLIGHT], // SPR_GSNL
&lspr[NOLIGHT], // SPR_GSNH
&lspr[NOLIGHT], // SPR_MNUS
&lspr[NOLIGHT], // SPR_MNUD
&lspr[NOLIGHT], // SPR_SSHL
&lspr[NOLIGHT], // SPR_UNID
&lspr[NOLIGHT], // SPR_CANA
&lspr[NOLIGHT], // SPR_CANG
// Generic Boos Items
&lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes
@ -350,6 +355,19 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_WWSG
&lspr[NOLIGHT], // SPR_WWS2
&lspr[NOLIGHT], // SPR_WWS3
&lspr[NOLIGHT], // SPR_OILL
&lspr[NOLIGHT], // SPR_OILF
&lspr[NOLIGHT], // SPR_BARR
&lspr[NOLIGHT], // SPR_REMT
&lspr[NOLIGHT], // SPR_TAZD
&lspr[NOLIGHT], // SPR_ADST
&lspr[NOLIGHT], // SPR_MCRT
&lspr[NOLIGHT], // SPR_MCSP
&lspr[NOLIGHT], // SPR_NON2
&lspr[NOLIGHT], // SPR_SALD
&lspr[NOLIGHT], // SPR_TRAE
&lspr[NOLIGHT], // SPR_TRAI
&lspr[NOLIGHT], // SPR_STEA
// Red Volcano Scenery
&lspr[REDBALL_L], // SPR_FLME
@ -542,6 +560,7 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[SUPERSPARK_L], // SPR_BOM3
&lspr[NOLIGHT], // SPR_BOM4
&lspr[REDBALL_L], // SPR_BMNB
&lspr[NOLIGHT], // SPR_WDDB
// Crumbly rocks
&lspr[NOLIGHT], // SPR_ROIA

File diff suppressed because it is too large Load Diff

View File

@ -115,6 +115,9 @@ void A_CrushclawAim();
void A_CrushclawLaunch();
void A_VultureVtol();
void A_VultureCheck();
void A_VultureHover();
void A_VultureBlast();
void A_VultureFly();
void A_SkimChase();
void A_SkullAttack();
void A_LobShot();
@ -251,6 +254,17 @@ void A_Boss5PinchShot();
void A_Boss5MakeItRain();
void A_LookForBetter();
void A_Boss5BombExplode();
void A_DustDevilThink();
void A_TNTExplode();
void A_DebrisRandom();
void A_TrainCameo();
void A_TrainCameo2();
void A_CanarivoreGas();
void A_KillSegments();
void A_SnapperSpawn();
void A_SnapperThinker();
void A_SaloonDoorSpawn();
void A_MinecartSparkThink();
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
#define NUMMOBJFREESLOTS 512
@ -291,9 +305,14 @@ typedef enum sprite
SPR_SPSH, // Egg Guard
SPR_ESHI, // Egg Guard's shield
SPR_GSNP, // Green Snapper
SPR_GSNL, // Green Snapper leg
SPR_GSNH, // Green Snapper head
SPR_MNUS, // Minus
SPR_MNUD, // Minus dirt
SPR_SSHL, // Spring Shell
SPR_UNID, // Unidus
SPR_CANA, // Canarivore
SPR_CANG, // Canarivore gas
// Generic Boss Items
SPR_JETF, // Boss jet fumes
@ -476,6 +495,19 @@ typedef enum sprite
SPR_WWSG, // Caution Sign
SPR_WWS2, // Cacti Sign
SPR_WWS3, // Sharp Turn Sign
SPR_OILL, // Oil lamp
SPR_OILF, // Oil lamp flare
SPR_BARR, // TNT barrel
SPR_REMT, // TNT proximity shell
SPR_TAZD, // Dust devil
SPR_ADST, // Arid dust
SPR_MCRT, // Minecart
SPR_MCSP, // Minecart spark
SPR_NON2, // Saloon door thinker
SPR_SALD, // Saloon door
SPR_TRAE, // Train cameo locomotive
SPR_TRAI, // Train cameo wagon
SPR_STEA, // Train steam
// Red Volcano Scenery
SPR_FLME, // Flame jet
@ -668,6 +700,7 @@ typedef enum sprite
SPR_BOM3, // Boss Explosion 2
SPR_BOM4, // Underwater Explosion
SPR_BMNB, // Mine Explosion
SPR_WDDB, // Wood Debris
// Crumbly rocks
SPR_ROIA,
@ -1126,15 +1159,10 @@ typedef enum state
// Vulture
S_VULTURE_STND,
S_VULTURE_VTOL1,
S_VULTURE_VTOL2,
S_VULTURE_VTOL3,
S_VULTURE_VTOL4,
S_VULTURE_DRIFT,
S_VULTURE_ZOOM1,
S_VULTURE_ZOOM2,
S_VULTURE_ZOOM3,
S_VULTURE_ZOOM4,
S_VULTURE_ZOOM5,
S_VULTURE_STUNNED,
// Pointy
S_POINTY1,
@ -1185,15 +1213,31 @@ typedef enum state
S_EGGSHIELDBREAK,
// Green Snapper
S_SNAPPER_SPAWN,
S_SNAPPER_SPAWN2,
S_GSNAPPER_STND,
S_GSNAPPER1,
S_GSNAPPER2,
S_GSNAPPER3,
S_GSNAPPER4,
S_SNAPPER_XPLD,
S_SNAPPER_LEG,
S_SNAPPER_LEGRAISE,
S_SNAPPER_HEAD,
// Minus
S_MINUS_INIT,
S_MINUS_STND,
S_MINUS_DIGGING,
S_MINUS_DIGGING1,
S_MINUS_DIGGING2,
S_MINUS_DIGGING3,
S_MINUS_DIGGING4,
S_MINUS_BURST0,
S_MINUS_BURST1,
S_MINUS_BURST2,
S_MINUS_BURST3,
S_MINUS_BURST4,
S_MINUS_BURST5,
S_MINUS_POPUP,
S_MINUS_UPWARD1,
S_MINUS_UPWARD2,
@ -1212,6 +1256,15 @@ typedef enum state
S_MINUS_DOWNWARD7,
S_MINUS_DOWNWARD8,
// Minus dirt
S_MINUSDIRT1,
S_MINUSDIRT2,
S_MINUSDIRT3,
S_MINUSDIRT4,
S_MINUSDIRT5,
S_MINUSDIRT6,
S_MINUSDIRT7,
// Spring Shell
S_SSHELL_STND,
S_SSHELL_RUN1,
@ -1239,6 +1292,28 @@ typedef enum state
S_UNIDUS_RUN,
S_UNIDUS_BALL,
// Canarivore
S_CANARIVORE_LOOK,
S_CANARIVORE_AWAKEN1,
S_CANARIVORE_AWAKEN2,
S_CANARIVORE_AWAKEN3,
S_CANARIVORE_GAS1,
S_CANARIVORE_GAS2,
S_CANARIVORE_GAS3,
S_CANARIVORE_GAS4,
S_CANARIVORE_GAS5,
S_CANARIVORE_GASREPEAT,
S_CANARIVORE_CLOSE1,
S_CANARIVORE_CLOSE2,
S_CANARIVOREGAS_1,
S_CANARIVOREGAS_2,
S_CANARIVOREGAS_3,
S_CANARIVOREGAS_4,
S_CANARIVOREGAS_5,
S_CANARIVOREGAS_6,
S_CANARIVOREGAS_7,
S_CANARIVOREGAS_8,
// Boss Explosion
S_BOSSEXPLODE,
@ -2426,6 +2501,85 @@ typedef enum state
S_ARIDSIGN_CACTI,
S_ARIDSIGN_SHARPTURN,
// Oil lamp
S_OILLAMP,
S_OILLAMPFLARE,
// TNT barrel
S_TNTBARREL_STND1,
S_TNTBARREL_EXPL1,
S_TNTBARREL_EXPL2,
S_TNTBARREL_EXPL3,
S_TNTBARREL_EXPL4,
S_TNTBARREL_EXPL5,
S_TNTBARREL_EXPL6,
S_TNTBARREL_FLYING,
// TNT proximity shell
S_PROXIMITY_TNT,
S_PROXIMITY_TNT_TRIGGER1,
S_PROXIMITY_TNT_TRIGGER2,
S_PROXIMITY_TNT_TRIGGER3,
S_PROXIMITY_TNT_TRIGGER4,
S_PROXIMITY_TNT_TRIGGER5,
S_PROXIMITY_TNT_TRIGGER6,
S_PROXIMITY_TNT_TRIGGER7,
S_PROXIMITY_TNT_TRIGGER8,
S_PROXIMITY_TNT_TRIGGER9,
S_PROXIMITY_TNT_TRIGGER10,
S_PROXIMITY_TNT_TRIGGER11,
S_PROXIMITY_TNT_TRIGGER12,
S_PROXIMITY_TNT_TRIGGER13,
S_PROXIMITY_TNT_TRIGGER14,
S_PROXIMITY_TNT_TRIGGER15,
S_PROXIMITY_TNT_TRIGGER16,
S_PROXIMITY_TNT_TRIGGER17,
S_PROXIMITY_TNT_TRIGGER18,
S_PROXIMITY_TNT_TRIGGER19,
S_PROXIMITY_TNT_TRIGGER20,
S_PROXIMITY_TNT_TRIGGER21,
S_PROXIMITY_TNT_TRIGGER22,
S_PROXIMITY_TNT_TRIGGER23,
// Dust devil
S_DUSTDEVIL,
S_DUSTLAYER1,
S_DUSTLAYER2,
S_DUSTLAYER3,
S_DUSTLAYER4,
S_DUSTLAYER5,
S_ARIDDUST1,
S_ARIDDUST2,
S_ARIDDUST3,
// Minecart
S_MINECART_IDLE,
S_MINECART_DTH1,
S_MINECARTEND,
S_MINECARTSEG_FRONT,
S_MINECARTSEG_BACK,
S_MINECARTSEG_LEFT,
S_MINECARTSEG_RIGHT,
S_MINECARTSIDEMARK1,
S_MINECARTSIDEMARK2,
S_MINECARTSPARK,
// Saloon door
S_SALOONDOOR,
S_SALOONDOORTHINKER,
// Train cameo
S_TRAINCAMEOSPAWNER_1,
S_TRAINCAMEOSPAWNER_2,
S_TRAINCAMEOSPAWNER_3,
S_TRAINCAMEOSPAWNER_4,
S_TRAINCAMEOSPAWNER_5,
S_TRAINPUFFMAKER,
// Train
S_TRAINDUST,
S_TRAINSTEAM,
// Flame jet
S_FLAMEJETSTND,
S_FLAMEJETSTART,
@ -3748,6 +3902,8 @@ typedef enum state
S_DUST3,
S_DUST4,
S_WOODDEBRIS,
S_ROCKSPAWN,
S_ROCKCRUMBLEA,
@ -3831,11 +3987,16 @@ typedef enum mobj_type
MT_EGGGUARD, // Egg Guard
MT_EGGSHIELD, // Egg Guard's shield
MT_GSNAPPER, // Green Snapper
MT_SNAPPER_LEG, // Green Snapper leg
MT_SNAPPER_HEAD, // Green Snapper head
MT_MINUS, // Minus
MT_MINUSDIRT, // Minus dirt
MT_SPRINGSHELL, // Spring Shell
MT_YELLOWSHELL, // Spring Shell (yellow)
MT_UNIDUS, // Unidus
MT_UNIBALL, // Unidus Ball
MT_CANARIVORE, // Canarivore
MT_CANARIVORE_GAS, // Canarivore gas
// Generic Boss Items
MT_BOSSEXPLODE,
@ -4134,6 +4295,26 @@ typedef enum mobj_type
MT_ARIDSIGN_CAUTION, // Caution Sign
MT_ARIDSIGN_CACTI, // Cacti Sign
MT_ARIDSIGN_SHARPTURN, // Sharp Turn Sign
MT_OILLAMP,
MT_TNTBARREL,
MT_PROXIMITYTNT,
MT_DUSTDEVIL,
MT_DUSTLAYER,
MT_ARIDDUST,
MT_MINECART,
MT_MINECARTSEG,
MT_MINECARTSPAWNER,
MT_MINECARTEND,
MT_MINECARTENDSOLID,
MT_MINECARTSIDEMARK,
MT_MINECARTSPARK,
MT_SALOONDOOR,
MT_SALOONDOORTHINKER,
MT_TRAINCAMEOSPAWNER,
MT_TRAINSEG,
MT_TRAINDUSTSPAWNER,
MT_TRAINSTEAMSPAWNER,
MT_MINECARTSWITCHPOINT,
// Red Volcano Scenery
MT_FLAMEJET,
@ -4456,6 +4637,7 @@ typedef enum mobj_type
MT_EXPLODE, // Robot Explosion
MT_UWEXPLODE, // Underwater Explosion
MT_DUST,
MT_WOODDEBRIS,
MT_ROCKSPAWNER,
MT_FALLINGROCK,
MT_ROCKCRUMBLE1,

File diff suppressed because it is too large Load Diff

View File

@ -1699,6 +1699,73 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
return;
case MT_CANARIVORE_GAS:
// if player and gas touch, attach gas to player (overriding any gas that already attached) and apply slowdown effect
P_UnsetThingPosition(special);
special->x = toucher->x - toucher->momx/2;
special->y = toucher->y - toucher->momy/2;
special->z = toucher->z - toucher->momz/2;
P_SetThingPosition(special);
toucher->momx = FixedMul(toucher->momx, 50*FRACUNIT/51);
toucher->momy = FixedMul(toucher->momy, 50*FRACUNIT/51);
special->momx = toucher->momx;
special->momy = toucher->momy;
special->momz = toucher->momz;
return;
case MT_MINECARTSPAWNER:
if (!special->fuse || player->powers[pw_carry] != CR_MINECART)
{
mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART);
P_SetTarget(&mcart->target, toucher);
mcart->angle = toucher->angle = player->drawangle = special->angle;
mcart->friction = FRACUNIT;
P_ResetPlayer(player);
player->pflags |= PF_JUMPDOWN;
player->powers[pw_carry] = CR_MINECART;
toucher->player->pflags &= ~PF_APPLYAUTOBRAKE;
P_SetTarget(&toucher->tracer, mcart);
toucher->momx = toucher->momy = toucher->momz = 0;
special->fuse = 3*TICRATE;
special->flags2 |= MF2_DONTDRAW;
}
return;
case MT_MINECARTEND:
if (player->powers[pw_carry] == CR_MINECART && toucher->tracer && !P_MobjWasRemoved(toucher->tracer) && toucher->tracer->health)
{
fixed_t maxz = max(toucher->z, special->z + 35*special->scale);
toucher->momx = toucher->tracer->momx/2;
toucher->momy = toucher->tracer->momy/2;
toucher->momz = toucher->tracer->momz + P_AproxDistance(toucher->tracer->momx, toucher->tracer->momy)/2;
P_ResetPlayer(player);
player->pflags &= ~PF_APPLYAUTOBRAKE;
P_SetPlayerMobjState(toucher, S_PLAY_FALL);
P_SetTarget(&toucher->tracer->target, NULL);
P_KillMobj(toucher->tracer, toucher, special, 0);
P_SetTarget(&toucher->tracer, NULL);
player->powers[pw_carry] = CR_NONE;
P_UnsetThingPosition(toucher);
toucher->x = special->x;
toucher->y = special->y;
toucher->z = maxz;
P_SetThingPosition(toucher);
}
return;
case MT_MINECARTSWITCHPOINT:
if (player->powers[pw_carry] == CR_MINECART && toucher->tracer && !P_MobjWasRemoved(toucher->tracer) && toucher->tracer->health)
{
mobjflag2_t destambush = special->flags2 & MF2_AMBUSH;
angle_t angdiff = toucher->tracer->angle - special->angle;
if (angdiff > ANGLE_90 && angdiff < ANGLE_270)
destambush ^= MF2_AMBUSH;
toucher->tracer->flags2 = (toucher->tracer->flags2 & ~MF2_AMBUSH) | destambush;
}
return;
default: // SOC or script pickup
if (player->bot)
return;
@ -2546,6 +2613,13 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
target->fuse = TICRATE*2;
break;
case MT_MINECART:
A_Scream(target);
target->momx = target->momy = target->momz = 0;
if (target->target && target->target->health)
P_KillMobj(target->target, target, source, 0);
break;
case MT_PLAYER:
{
target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player)
@ -2960,6 +3034,9 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
P_ResetPlayer(player);
if (!player->spectator)
player->mo->flags2 &= ~MF2_DONTDRAW;
P_SetPlayerMobjState(player->mo, player->mo->info->deathstate);
if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{
@ -3591,9 +3668,6 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
}
if (player->mo->eflags & MFE_VERTICALFLIP)
mo->momz *= -1;
if (P_IsObjectOnGround(player->mo))
player->powers[pw_carry] = CR_NONE;
}
player->losstime += 10*TICRATE;

View File

@ -229,6 +229,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state);
boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
void P_RunShields(void);
void P_RunOverlays(void);
void P_HandleMinecartSegments(mobj_t *mobj);
void P_MobjThinker(mobj_t *mobj);
boolean P_RailThinker(mobj_t *mobj);
void P_PushableThinker(mobj_t *mobj);

View File

@ -818,6 +818,83 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
#endif
if (tmthing->type == MT_MINECART)
{
//height check
if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !(thing->health))
return true;
if (thing->type == MT_TNTBARREL)
P_KillMobj(thing, tmthing, tmthing->target, 0);
else if ((thing->flags & MF_MONITOR) || (thing->flags & MF_ENEMY))
{
P_KillMobj(thing, tmthing, tmthing->target, 0);
if (tmthing->momz*P_MobjFlip(tmthing) < 0)
tmthing->momz = abs(tmthing->momz)*P_MobjFlip(tmthing);
}
}
if (thing->type == MT_SALOONDOOR && tmthing->player)
{
if (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer) && tmthing->tracer->health)
{
fixed_t dx = tmthing->tracer->momx;
fixed_t dy = tmthing->tracer->momy;
fixed_t dm = min(FixedHypot(dx, dy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, dx, dy) - thing->angle;
fixed_t s = FINESINE((ang >> ANGLETOFINESHIFT) & FINEMASK);
S_StartSound(tmthing, thing->info->activesound);
thing->extravalue2 += 2*FixedMul(s, dm)/3;
return true;
}
}
if (thing->type == MT_TNTBARREL && tmthing->player)
{
if (tmthing->momz < 0)
{
if (tmthing->z + tmthing->momz > thing->z + thing->height)
return true;
}
else
{
if (tmthing->z > thing->z + thing->height)
return true;
}
if (tmthing->momz > 0)
{
if (tmthing->z + tmthing->height + tmthing->momz < thing->z)
return true;
}
else
{
if (tmthing->z + tmthing->height < thing->z)
return true;
}
if ((tmthing->player->pflags & (PF_SPINNING | PF_GLIDING))
|| ((tmthing->player->pflags & PF_JUMPED)
&& (!(tmthing->player->pflags & PF_NOJUMPDAMAGE)
|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|| ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING)
&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height / 2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))
|| (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY)))
P_DamageMobj(thing, tmthing, tmthing, 1, 0);
}
if (thing->type == MT_VULTURE && tmthing->type == MT_VULTURE)
{
fixed_t dx = thing->x - tmthing->x;
fixed_t dy = thing->y - tmthing->y;
fixed_t dz = thing->z - tmthing->z;
fixed_t dm = FixedHypot(dz, FixedHypot(dx, dy));
thing->momx += FixedDiv(dx, dm);
thing->momy += FixedDiv(dy, dm);
thing->momz += FixedDiv(dz, dm);
}
if (tmthing->type == MT_FANG && thing->type == MT_FSGNB)
{
if (thing->z > tmthing->z + tmthing->height)
@ -1395,7 +1472,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_FAN || thing->type == MT_STEAM)
P_DoFanAndGasJet(thing, tmthing);
else if (thing->flags & MF_SPRING)
else if (thing->flags & MF_SPRING && tmthing->player->powers[pw_carry] != CR_MINECART)
{
if ( thing->z <= tmthing->z + tmthing->height
&& tmthing->z <= thing->z + thing->height)
@ -3859,6 +3936,8 @@ static boolean nofit;
static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
{
mobj_t *killer = NULL;
//If a thing is both pushable and vulnerable, it doesn't block the crusher because it gets killed.
boolean immunepushable = ((thing->flags & (MF_PUSHABLE | MF_SHOOTABLE)) == MF_PUSHABLE);
if (P_ThingHeightClip(thing))
{
@ -3877,7 +3956,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
// just be blocked by another object - check if it's really a ceiling!
if (thing->z + thing->height > thing->ceilingz && thing->z <= thing->ceilingz)
{
if (thing->flags & MF_PUSHABLE && thing->z + thing->height > thing->subsector->sector->ceilingheight)
if (immunepushable && thing->z + thing->height > thing->subsector->sector->ceilingheight)
{
//Thing is a pushable and blocks the moving ceiling
nofit = true;
@ -3885,7 +3964,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
}
//Check FOFs in the sector
if (thing->subsector->sector->ffloors && (realcrush || thing->flags & MF_PUSHABLE))
if (thing->subsector->sector->ffloors && (realcrush || immunepushable))
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
@ -3912,7 +3991,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
delta2 = thingtop - (bottomheight + topheight)/2;
if (bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2))
{
if (thing->flags & MF_PUSHABLE)
if (immunepushable)
{
//FOF is blocked by pushable
nofit = true;

View File

@ -2580,9 +2580,9 @@ static boolean P_ZMovement(mobj_t *mo)
if (!mo->player && P_CheckDeathPitCollide(mo))
{
if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS)
if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART)
{
// Kill enemies and bosses that fall into death pits.
// Kill enemies, bosses and minecarts that fall into death pits.
if (mo->health)
{
P_KillMobj(mo, NULL, NULL, 0);
@ -6728,6 +6728,67 @@ static void P_KoopaThinker(mobj_t *koopa)
}
}
// Spawns and chains the minecart sides.
static void P_SpawnMinecartSegments(mobj_t *mobj, boolean mode)
{
fixed_t x = mobj->x;
fixed_t y = mobj->y;
fixed_t z = mobj->z;
mobj_t *prevseg = mobj;
mobj_t *seg;
UINT8 i;
for (i = 0; i < 4; i++)
{
seg = P_SpawnMobj(x, y, z, MT_MINECARTSEG);
P_SetMobjState(seg, (statenum_t)(S_MINECARTSEG_FRONT + i));
if (i >= 2)
seg->extravalue1 = (i == 2) ? -18 : 18;
else
{
seg->extravalue2 = (i == 0) ? 24 : -24;
seg->cusval = -90;
}
if (!mode)
seg->frame &= ~FF_ANIMATE;
P_SetTarget(&prevseg->tracer, seg);
prevseg = seg;
}
}
// Updates the chained segments.
static void P_UpdateMinecartSegments(mobj_t *mobj)
{
mobj_t *seg = mobj->tracer;
fixed_t x = mobj->x;
fixed_t y = mobj->y;
fixed_t z = mobj->z;
angle_t ang = mobj->angle;
angle_t fa = (ang >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t c = FINECOSINE(fa);
fixed_t s = FINESINE(fa);
INT32 dx, dy;
INT32 sang;
while (seg)
{
dx = seg->extravalue1;
dy = seg->extravalue2;
sang = seg->cusval;
P_TeleportMove(seg, x + s*dx + c*dy, y - c*dx + s*dy, z);
seg->angle = ang + FixedAngle(FRACUNIT*sang);
seg->flags2 = (seg->flags2 & ~MF2_DONTDRAW) | (mobj->flags2 & MF2_DONTDRAW);
seg = seg->tracer;
}
}
void P_HandleMinecartSegments(mobj_t *mobj)
{
if (!mobj->tracer)
P_SpawnMinecartSegments(mobj, (mobj->type == MT_MINECART));
P_UpdateMinecartSegments(mobj);
}
//
// P_MobjThinker
//
@ -7502,38 +7563,35 @@ void P_MobjThinker(mobj_t *mobj)
break;
case MT_PLAYER:
/// \todo Have the player's dead body completely finish its animation even if they've already respawned.
if (!(mobj->flags2 & MF2_DONTDRAW))
{
if (!mobj->fuse)
{ // Go away.
/// \todo Actually go ahead and remove mobj completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it.
mobj->momz = 0;
if (mobj->player)
mobj->flags2 |= MF2_DONTDRAW;
else // safe to remove, nobody's going to complain!
{
P_RemoveMobj(mobj);
return;
}
}
else // Apply gravity to fall downwards.
if (!mobj->fuse)
{ // Go away.
/// \todo Actually go ahead and remove mobj completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it.
mobj->momz = 0;
if (mobj->player)
mobj->flags2 |= MF2_DONTDRAW;
else // safe to remove, nobody's going to complain!
{
if (mobj->player && !(mobj->fuse % 8) && (mobj->player->charflags & SF_MACHINE))
{
fixed_t r = mobj->radius>>FRACBITS;
mobj_t *explosion = P_SpawnMobj(
mobj->x + (P_RandomRange(r, -r)<<FRACBITS),
mobj->y + (P_RandomRange(r, -r)<<FRACBITS),
mobj->z + (P_RandomKey(mobj->height>>FRACBITS)<<FRACBITS),
MT_BOSSEXPLODE);
S_StartSound(explosion, sfx_cybdth);
}
if (mobj->movedir == DMG_DROWNED)
P_SetObjectMomZ(mobj, -FRACUNIT/2, true); // slower fall from drowning
else
P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true);
P_RemoveMobj(mobj);
return;
}
}
else // Apply gravity to fall downwards.
{
if (mobj->player && !(mobj->fuse % 8) && (mobj->player->charflags & SF_MACHINE))
{
fixed_t r = mobj->radius >> FRACBITS;
mobj_t *explosion = P_SpawnMobj(
mobj->x + (P_RandomRange(r, -r) << FRACBITS),
mobj->y + (P_RandomRange(r, -r) << FRACBITS),
mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS),
MT_BOSSEXPLODE);
S_StartSound(explosion, sfx_cybdth);
}
if (mobj->movedir == DMG_DROWNED)
P_SetObjectMomZ(mobj, -FRACUNIT / 2, true); // slower fall from drowning
else
P_SetObjectMomZ(mobj, -2 * FRACUNIT / 3, true);
}
break;
default:
break;
@ -8412,6 +8470,114 @@ void P_MobjThinker(mobj_t *mobj)
mobj->flags2 |= MF2_DONTDRAW;
}
break;
case MT_TRAINDUSTSPAWNER:
if (leveltime % 5 == 0) {
mobj_t *traindust = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PARTICLE);
traindust->flags = MF_SCENERY;
P_SetMobjState(traindust, S_TRAINDUST);
traindust->frame = P_RandomRange(0, 8) | FF_TRANS90;
traindust->angle = mobj->angle;
traindust->tics = TICRATE * 4;
traindust->destscale = FRACUNIT * 64;
traindust->scalespeed = FRACUNIT / 24;
P_SetScale(traindust, FRACUNIT * 6);
}
break;
case MT_TRAINSTEAMSPAWNER:
if (leveltime % 5 == 0) {
mobj_t *steam = P_SpawnMobj(mobj->x + FRACUNIT*P_SignedRandom() / 2, mobj->y + FRACUNIT*P_SignedRandom() / 2, mobj->z, MT_PARTICLE);
P_SetMobjState(steam, S_TRAINSTEAM);
steam->frame = P_RandomRange(0, 1) | FF_TRANS90;
steam->tics = TICRATE * 8;
steam->destscale = FRACUNIT * 64;
steam->scalespeed = FRACUNIT / 8;
P_SetScale(steam, FRACUNIT * 16);
steam->momx = P_SignedRandom() * 32;
steam->momy = -64 * FRACUNIT;
steam->momz = 2 * FRACUNIT;
}
break;
case MT_CANARIVORE_GAS:
{
fixed_t momz;
if (mobj->flags2 & MF2_AMBUSH)
{
mobj->momx = FixedMul(mobj->momx, 50 * FRACUNIT / 51);
mobj->momy = FixedMul(mobj->momy, 50 * FRACUNIT / 51);
break;
}
if (mobj->eflags & MFE_VERTICALFLIP)
{
if ((mobj->z + mobj->height + mobj->momz) <= mobj->ceilingz)
break;
}
else
{
if ((mobj->z + mobj->momz) >= mobj->floorz)
break;
}
momz = abs(mobj->momz);
if (R_PointToDist2(0, 0, mobj->momx, mobj->momy) < momz)
P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), momz);
mobj->flags |= MF_NOGRAVITY|MF_NOCLIPHEIGHT;
mobj->flags2 |= MF2_AMBUSH;
break;
}
case MT_SALOONDOOR:
{
fixed_t x = mobj->tracer->x;
fixed_t y = mobj->tracer->y;
fixed_t z = mobj->tracer->z;
angle_t oang = FixedAngle(mobj->extravalue1);
angle_t fa = (oang >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t c0 = -96*FINECOSINE(fa);
fixed_t s0 = -96*FINESINE(fa);
angle_t fma;
fixed_t c, s;
angle_t angdiff;
// Adjust angular speed
fixed_t da = AngleFixed(mobj->angle - oang);
if (da > 180*FRACUNIT)
da -= 360*FRACUNIT;
mobj->extravalue2 = 8*(mobj->extravalue2 - da/32)/9;
// Update angle
mobj->angle += FixedAngle(mobj->extravalue2);
angdiff = mobj->angle - FixedAngle(mobj->extravalue1);
if (angdiff > (ANGLE_90 - ANG2) && angdiff < ANGLE_180)
{
mobj->angle = FixedAngle(mobj->extravalue1) + (ANGLE_90 - ANG2);
mobj->extravalue2 /= 2;
}
else if (angdiff < (ANGLE_270 + ANG2) && angdiff >= ANGLE_180)
{
mobj->angle = FixedAngle(mobj->extravalue1) + (ANGLE_270 + ANG2);
mobj->extravalue2 /= 2;
}
// Update position
fma = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK;
c = 48*FINECOSINE(fma);
s = 48*FINESINE(fma);
P_TeleportMove(mobj, x + c0 + c, y + s0 + s, z);
break;
}
case MT_MINECARTSPAWNER:
P_HandleMinecartSegments(mobj);
if (!mobj->fuse || mobj->fuse > TICRATE)
break;
if (mobj->fuse == 2)
{
mobj->fuse = 0;
break;
}
mobj->flags2 ^= MF2_DONTDRAW;
break;
case MT_SPINFIRE:
if (mobj->flags & MF_NOGRAVITY)
{
@ -8488,6 +8654,10 @@ void P_MobjThinker(mobj_t *mobj)
// Check fuse
if (mobj->fuse)
{
if (mobj->type == MT_SNAPPER_HEAD || mobj->type == MT_SNAPPER_LEG || mobj->type == MT_MINECARTSEG)
mobj->flags2 ^= MF2_DONTDRAW;
mobj->fuse--;
if (!mobj->fuse)
{
@ -8789,6 +8959,16 @@ void P_PushableThinker(mobj_t *mobj)
if (mobj->flags & MF_PUSHABLE && !(mobj->momx || mobj->momy))
P_TryMove(mobj, mobj->x, mobj->y, true);
if (mobj->type == MT_MINECART && mobj->health)
{
// If player is ded, remove this minecart
if (!mobj->target || P_MobjWasRemoved(mobj->target) || !mobj->target->health || !mobj->target->player || mobj->target->player->powers[pw_carry] != CR_MINECART)
{
P_KillMobj(mobj, NULL, NULL, 0);
return;
}
}
if (mobj->fuse == 1) // it would explode in the MobjThinker code
{
mobj_t *spawnmo;
@ -9152,6 +9332,20 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
case MT_FBOMB:
mobj->flags2 |= MF2_EXPLOSION;
break;
case MT_OILLAMP:
{
mobj_t* overlay = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY);
P_SetTarget(&overlay->target, mobj);
P_SetMobjState(overlay, S_OILLAMPFLARE);
break;
}
case MT_TNTBARREL:
mobj->momx = 1; //stack hack
break;
case MT_MINECARTEND:
mobj->tracer = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID);
mobj->tracer->angle = mobj->angle + ANGLE_90;
break;
default:
break;
}

View File

@ -963,7 +963,7 @@ void P_ResetPlayer(player_t *player)
{
player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_THOKKED|PF_CANCARRY|PF_SHIELDABILITY|PF_BOUNCING);
if (!(player->powers[pw_carry] == CR_NIGHTSMODE || player->powers[pw_carry] == CR_NIGHTSFALL || player->powers[pw_carry] == CR_BRAKGOOP))
if (!(player->powers[pw_carry] == CR_NIGHTSMODE || player->powers[pw_carry] == CR_NIGHTSFALL || player->powers[pw_carry] == CR_BRAKGOOP || player->powers[pw_carry] == CR_MINECART))
player->powers[pw_carry] = CR_NONE;
player->secondjump = 0;
@ -9753,6 +9753,417 @@ void P_DoPityCheck(player_t *player)
}
}
static sector_t *P_GetMinecartSector(fixed_t x, fixed_t y, fixed_t z, fixed_t *nz)
{
sector_t *sec = R_PointInSubsector(x, y)->sector;
if ((sec->ceilingheight - sec->floorheight) < 64*FRACUNIT)
return NULL;
if (sec->ffloors)
{
ffloor_t *rover;
for (rover = sec->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
*nz = *rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : *rover->topheight;
if (abs(z - *nz) <= 56*FRACUNIT)
{
sec = &sectors[rover->secnum];
return sec;
}
}
}
*nz = sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : sec->floorheight;
if (abs(z - *nz) > 56*FRACUNIT)
return NULL;
return sec;
}
static INT32 P_GetMinecartSpecialLine(sector_t *sec)
{
INT32 line = -1;
if (!sec)
return line;
if (sec->tag != 0)
line = P_FindSpecialLineFromTag(16, sec->tag, -1);
// Also try for lines facing the sector itself, with tag 0.
{
UINT32 i;
for (i = 0; i < sec->linecount; i++)
{
line_t *li = sec->lines[i];
if (li->tag == 0 && li->special == 16 && li->frontsector == sec)
line = li - lines;
}
}
return line;
}
// Get an axis of a certain ID number
static mobj_t *P_GetAxis(INT32 num)
{
thinker_t *th;
mobj_t *mobj;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mobj = (mobj_t *)th;
// NiGHTS axes spawn before anything else. If this mobj doesn't have MF2_AXIS, it means we reached the axes' end.
if (!(mobj->flags2 & MF2_AXIS))
break;
// Skip if this axis isn't the one we want.
if (mobj->health != num)
continue;
return mobj;
}
CONS_Alert(CONS_WARNING, "P_GetAxis: Track segment %d is missing!\n", num);
return NULL;
}
// Auxiliary function. For a given position and axis, it calculates the nearest "valid" snap-on position.
static void P_GetAxisPosition(fixed_t x, fixed_t y, mobj_t *amo, fixed_t *newx, fixed_t *newy, angle_t *targetangle, angle_t *grind)
{
fixed_t ax = amo->x;
fixed_t ay = amo->y;
angle_t ang;
angle_t gr = 0;
if (amo->type == MT_AXISTRANSFERLINE)
{
ang = amo->angle;
// Extra security for cardinal directions.
if (ang == ANGLE_90 || ang == ANGLE_270) // Vertical lines
x = ax;
else if (ang == 0 || ang == ANGLE_180) // Horizontal lines
y = ay;
else // Diagonal lines
{
fixed_t distance = R_PointToDist2(ax, ay, x, y);
angle_t fad = ((R_PointToAngle2(ax, ay, x, y) - ang) >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t cosine = FINECOSINE(fad);
angle_t fa = (ang >> ANGLETOFINESHIFT) & FINEMASK;
distance = FixedMul(distance, cosine);
x = ax + FixedMul(distance, FINECOSINE(fa));
y = ay + FixedMul(distance, FINESINE(fa));
}
}
else // Keep minecart to circle
{
fixed_t rad = amo->radius;
fixed_t distfactor = FixedDiv(rad, R_PointToDist2(ax, ay, x, y));
gr = R_PointToAngle2(ax, ay, x, y);
ang = gr + ANGLE_90;
x = ax + FixedMul(x - ax, distfactor);
y = ay + FixedMul(y - ay, distfactor);
}
*newx = x;
*newy = y;
*targetangle = ang;
*grind = gr;
}
static void P_SpawnSparks(mobj_t *mo, angle_t maindir)
{
angle_t fa = (mo->angle >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t c = FixedMul(FINECOSINE(fa), mo->radius);
fixed_t s = FixedMul(FINESINE(fa), mo->radius);
mobj_t *spark;
SINT8 b1 = (leveltime & 1) ? 1 : -1;
SINT8 b2 = (leveltime & 2) ? 1 : -1;
fixed_t r1 = FRACUNIT*P_RandomRange(-1, 1);
fixed_t r2 = FRACUNIT*P_RandomRange(-1, 1);
fixed_t r3 = FRACUNIT*P_RandomRange(-1, 1);
fixed_t fm = (maindir >> ANGLETOFINESHIFT) & FINEMASK;
spark = P_SpawnMobj(mo->x - b2*s + b1*c, mo->y + b2*c + b1*s, mo->z, MT_MINECARTSPARK);
spark->momx = mo->momx + r1 + 8*FINECOSINE(fm);
spark->momy = mo->momy + r2 + 8*FINESINE(fm);
spark->momz = mo->momz + r3;
P_Thrust(spark, R_PointToAngle2(mo->x, mo->y, spark->x, spark->y), 8*FRACUNIT);
P_SetScale(spark, FRACUNIT/4);
spark->destscale = spark->scale;
spark->fuse = TICRATE/3;
}
// Performs a proximity check on a given direction looking for rails.
static mobj_t *P_LookForRails(mobj_t* mobj, fixed_t c, fixed_t s, angle_t targetangle, fixed_t xcom, fixed_t ycom)
{
INT16 interval = 16;
INT16 fwooffset = FixedHypot(mobj->momx, mobj->momy) >> FRACBITS;
fixed_t x = mobj->x;
fixed_t y = mobj->y;
fixed_t z = mobj->z;
UINT8 i;
for (i = 4; i <= 10; i++)
{
fixed_t nz;
INT32 lline;
x += interval*xcom*i + fwooffset*c*i;
y += interval*ycom*i + fwooffset*s*i;
lline = P_GetMinecartSpecialLine(P_GetMinecartSector(x, y, z, &nz));
if (lline != -1)
{
fixed_t nx, ny;
angle_t nang, dummy, angdiff;
mobj_t *mark;
mobj_t *snax = P_GetAxis(sides[lines[lline].sidenum[0]].textureoffset >> FRACBITS);
if (!snax)
return NULL;
P_GetAxisPosition(x, y, snax, &nx, &ny, &nang, &dummy);
angdiff = ((nang - targetangle) + ANG10/2) & ~ANGLE_180;
//Axes must be directly parallel or antiparallel, give or take 5 degrees.
if (angdiff < ANG10)
{
mark = P_SpawnMobj(nx, ny, nz, mobj->info->raisestate);
return mark;
}
}
}
return NULL;
}
static void P_ParabolicMove(mobj_t *mo, fixed_t x, fixed_t y, fixed_t z, fixed_t g, fixed_t speed)
{
fixed_t dx = x - mo->x;
fixed_t dy = y - mo->y;
fixed_t dz = z - mo->z;
fixed_t dh = P_AproxDistance(dx, dy);
fixed_t c = FixedDiv(dx, dh);
fixed_t s = FixedDiv(dy, dh);
fixed_t fixConst = FixedDiv(speed, g);
mo->momx = FixedMul(c, speed);
mo->momy = FixedMul(s, speed);
mo->momz = FixedDiv(dh, 2*fixConst) + FixedDiv(dz, FixedDiv(dh, fixConst/2));
}
static void P_MinecartThink(player_t *player)
{
mobj_t *minecart = player->mo->tracer;
angle_t fa;
if (!minecart || P_MobjWasRemoved(minecart) || !minecart->health)
{
// Minecart died on you, so kill yourself.
P_KillMobj(player->mo, NULL, NULL, 0);
return;
}
//Limit player's angle to a cone.
#define MINECARTCONEMAX FixedAngle(20*FRACUNIT)
{
angle_t angdiff = player->mo->angle - minecart->angle;
if (angdiff < ANGLE_180 && angdiff > MINECARTCONEMAX)
player->mo->angle = minecart->angle + MINECARTCONEMAX;
else if (angdiff > ANGLE_180 && angdiff < InvAngle(MINECARTCONEMAX))
player->mo->angle = minecart->angle - MINECARTCONEMAX;
if (angdiff + minecart->angle != player->mo->angle && (!demoplayback || P_AnalogMove(player)))
{
if (player == &players[consoleplayer])
localangle = player->mo->angle;
else if (player == &players[secondarydisplayplayer])
localangle2 = player->mo->angle;
}
}
// Player holding jump?
if (!(player->cmd.buttons & BT_JUMP))
player->pflags &= ~PF_JUMPDOWN;
// Handle segments.
P_HandleMinecartSegments(minecart);
// Force 0 friction.
minecart->friction = FRACUNIT;
fa = (minecart->angle >> ANGLETOFINESHIFT) & FINEMASK;
if (!P_TryMove(minecart, minecart->x + FINECOSINE(fa), minecart->y + FINESINE(fa), true))
{
P_KillMobj(minecart, NULL, NULL, 0);
return;
}
if (P_IsObjectOnGround(minecart))
{
sector_t *sec;
INT32 lnum;
fixed_t dummy;
// Just hit floor.
if (minecart->eflags & MFE_JUSTHITFLOOR)
{
S_StopSound(minecart);
S_StartSound(minecart, sfx_s3k96);
}
sec = P_GetMinecartSector(minecart->x, minecart->y, minecart->z, &dummy);
if (sec)
lnum = P_GetMinecartSpecialLine(sec);
// Update axis if the cart is standing on a rail.
if (sec && lnum != -1)
{
mobj_t *axis = P_GetAxis(sides[lines[lnum].sidenum[0]].textureoffset >> FRACBITS);
fixed_t newx, newy;
angle_t targetangle, grind;
angle_t prevangle, angdiff;
mobj_t *detleft = NULL;
mobj_t *detright = NULL;
mobj_t *sidelock = NULL;
boolean jumped = false;
fixed_t currentSpeed;
if (!axis)
{
P_KillMobj(minecart, NULL, NULL, 0);
return;
}
minecart->movefactor = 0;
P_ResetScore(player);
// Handle angle and position
P_GetAxisPosition(minecart->x, minecart->y, axis, &newx, &newy, &targetangle, &grind);
if (axis->type != MT_AXISTRANSFERLINE)
P_SpawnSparks(minecart, grind);
P_TryMove(minecart, newx, newy, true);
// Set angle based on target
prevangle = minecart->angle;
angdiff = targetangle - minecart->angle;
if (angdiff < ANGLE_90 + ANG2 || angdiff > ANGLE_270 - ANG2)
minecart->angle = targetangle;
else
minecart->angle = targetangle + ANGLE_180;
angdiff = (minecart->angle - prevangle);
if (angdiff && (!demoplayback || P_AnalogMove(player))) // maintain relative angle on turns
{
player->mo->angle += angdiff;
if (player == &players[consoleplayer])
localangle += angdiff;
else if (player == &players[secondarydisplayplayer])
localangle2 += angdiff;
}
// Sideways detection
if (minecart->flags2 & MF2_AMBUSH)
{
angle_t fa2 = (minecart->angle >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t c = FINECOSINE(fa2);
fixed_t s = FINESINE(fa2);
detleft = P_LookForRails(minecart, c, s, targetangle, -s, c);
detright = P_LookForRails(minecart, c, s, targetangle, s, -c);
}
// How fast are we going?
currentSpeed = FixedHypot(minecart->momx, minecart->momy);
angdiff = R_PointToAngle2(0, 0, minecart->momx, minecart->momy) - minecart->angle;
if (angdiff > ANGLE_90 && angdiff < ANGLE_270)
currentSpeed *= -1;
// Player-specific behavior.
if (detleft && player->cmd.sidemove < 0)
sidelock = detleft;
else if (detright && player->cmd.sidemove > 0)
sidelock = detright;
//if (player->cmd.buttons & BT_USE && currentSpeed > 4*FRACUNIT)
// currentSpeed -= FRACUNIT/8;
// Jumping
if (sidelock || ((player->cmd.buttons & BT_JUMP) && !(player->pflags & PF_JUMPDOWN)))
{
player->pflags |= PF_JUMPDOWN;
if (minecart->eflags & MFE_ONGROUND)
minecart->eflags &= ~MFE_ONGROUND;
minecart->z += P_MobjFlip(minecart);
if (sidelock)
P_ParabolicMove(minecart, sidelock->x, sidelock->y, sidelock->z, gravity, max(currentSpeed, 10 * FRACUNIT));
else
minecart->momz = 10 * FRACUNIT;
S_StartSound(minecart, sfx_s3k51);
jumped = true;
}
if (!jumped)
{
// Natural acceleration and boosters
if (currentSpeed < minecart->info->speed)
currentSpeed += FRACUNIT/4;
if (minecart->standingslope)
{
fixed_t fa2 = (minecart->angle >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t front = P_GetZAt(minecart->standingslope, minecart->x, minecart->y);
fixed_t back = P_GetZAt(minecart->standingslope, minecart->x - FINECOSINE(fa2), minecart->y - FINESINE(fa2));
if (abs(front - back) < 3*FRACUNIT)
currentSpeed += (back - front)/3;
}
// Go forward at our current speed
P_InstaThrust(minecart, minecart->angle, currentSpeed);
// On-track ka-klong sound FX.
minecart->movecount += abs(currentSpeed);
if (minecart->movecount > 128*FRACUNIT)
{
minecart->movecount %= 128*FRACUNIT;
S_StartSound(minecart, minecart->info->activesound);
}
}
}
else
{
minecart->movefactor++;
if ((P_IsObjectOnGround(minecart) && minecart->movefactor >= 5) // off rail
|| (abs(minecart->momx) < minecart->scale/2 && abs(minecart->momy) < minecart->scale/2)) // hit a wall
{
P_KillMobj(minecart, NULL, NULL, 0);
return;
}
}
}
P_SetPlayerMobjState(player->mo, S_PLAY_STND);
// Move player to minecart.
P_TeleportMove(player->mo, minecart->x - minecart->momx, minecart->y - minecart->momy, minecart->z + max(minecart->momz, 0) + 8*FRACUNIT);
if (player->powers[pw_carry] != CR_MINECART)
return;
player->mo->momx = player->mo->momy = player->mo->momz = 0;
P_TryMove(player->mo, player->mo->x + minecart->momx, player->mo->y + minecart->momy, true);
if (player->powers[pw_flashing] == flashingtics)
player->powers[pw_flashing]--;
}
//
// P_PlayerThink
//
@ -10052,6 +10463,17 @@ void P_PlayerThink(player_t *player)
// for a bit after a teleport.
if (player->mo->reactiontime)
player->mo->reactiontime--;
else if (player->powers[pw_carry] == CR_MINECART)
{
if (!P_AnalogMove(player))
player->mo->angle = (cmd->angleturn << 16 /* not FRACBITS */);
ticruned++;
if ((cmd->angleturn & TICCMD_RECEIVED) == 0)
ticmiss++;
P_MinecartThink(player);
}
else if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && (player->powers[pw_carry] == CR_ROPEHANG || player->powers[pw_carry] == CR_ZOOMTUBE))
{
if (player->powers[pw_carry] == CR_ROPEHANG)
@ -10113,7 +10535,15 @@ void P_PlayerThink(player_t *player)
switch (player->powers[pw_carry])
{
case CR_PLAYER:
player->drawangle = (player->mo->tracer->player ? player->mo->tracer->player->drawangle : player->mo->tracer->angle);
if (player->mo->tracer->player)
{
player->drawangle = player->mo->tracer->player->drawangle;
break;
}
/* FALLTHRU */
case CR_MINECART:
case CR_GENERIC:
player->drawangle = player->mo->tracer->angle;
break;
/* -- in case we wanted to have the camera freely movable during zoom tubes
case CR_ZOOMTUBE:*/

View File

@ -195,6 +195,8 @@ sfxinfo_t S_sfx[NUMSFX] =
{"boingf", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bouncing"},
{"corkp", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cork fired"},
{"corkh", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cork hit"},
{"bowl", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bowling"},
{"chuchu", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Train horn"},
// Menu, interface
{"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"},
@ -311,13 +313,13 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pulse"},
{"s3k49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Impact"},
{"s3k4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Grab"},
{"s3k4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Water splash"},
{"s3k4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Splash"},
{"s3k4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy hit"},
{"s3k4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing bullet"},
{"s3k4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Big explosion"},
{"s3k4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flamethrower"},
{"s3k50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Siren"},
{"s3k51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling hazard"},
{"s3k51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling"},
{"s3k52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spike"},
{"s3k53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"},
{"s3k54", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Firing"}, // MetalSonic shot fire
@ -362,7 +364,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k7b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Soft bounce"},
{"s3k7c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Magnet"},
{"s3k7d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3k7e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Eating dirt"},
{"s3k7e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Dust"},
{"s3k7f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Freeze"},
{"s3k80", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ice spike burst"},
{"s3k81", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"},
@ -373,7 +375,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k86", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Alarm"},
{"s3k87", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"},
{"s3k88", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Metallic squeak"},
{"s3k89", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Advanced technology"},
{"s3k89", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Advanced tech"},
{"s3k8a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Boing"},
{"s3k8b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful hit"},
{"s3k8c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Humming power"},
@ -383,10 +385,10 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k90", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Impact"},
{"s3k91", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Closed"},
{"s3k92", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ghost"},
{"s3k93", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rebuilding"},
{"s3k93", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Gas release"},
{"s3k94", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spike"},
{"s3k95", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lava burst"},
{"s3k96", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling object"},
{"s3k96", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Landing"},
{"s3k97", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wind"},
{"s3k98", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling spike"},
{"s3k99", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"},
@ -454,13 +456,13 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3kcas", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Energy"},
{"s3kcal", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Energy"}, // ditto
{"s3kcbs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"},
{"s3kcbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominuous rumbling"}, // ditto
{"s3kcbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, // ditto
{"s3kccs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Collapsing"},
{"s3kccl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Collapsing"}, // ditto
{"s3kcds", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"},
{"s3kcdl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, // ditto
{"s3kces", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wind tunnel"},
{"s3kcel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wind tunnel"}, // ditto
{"s3kcel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Dust devil"}, // ditto
{"s3kcfs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3kcfl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto
{"s3kd0s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising"},
@ -469,8 +471,8 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3kd1l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto
{"s3kd2s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turning"},
{"s3kd2l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Moving chain"}, // ditto
{"s3kd3s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3kd3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto
{"s3kd3s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Digging"},
{"s3kd3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Digging"}, // ditto
{"s3kd4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Engine"},
{"s3kd4l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Engine"}, // ditto
{"s3kd5s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling lava"},

View File

@ -261,6 +261,8 @@ typedef enum
sfx_boingf,
sfx_corkp,
sfx_corkh,
sfx_bowl,
sfx_chuchu,
// Menu, interface
sfx_chchng,