diff --git a/src/d_player.h b/src/d_player.h index 69080bd9d..ff8c31203 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -234,7 +234,9 @@ typedef enum CR_ZOOMTUBE, CR_ROPEHANG, CR_MACESPIN, - CR_MINECART + CR_MINECART, + CR_ROLLOUT, + CR_PTERABYTE } carrytype_t; // pw_carry // Player powers. (don't edit this comment) diff --git a/src/dehacked.c b/src/dehacked.c index bd3bad362..8d240326d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -2447,6 +2447,14 @@ static actionpointer_t actionpointers[] = {{A_SaloonDoorSpawn}, "A_SALOONDOORSPAWN"}, {{A_MinecartSparkThink}, "A_MINECARTSPARKTHINK"}, {{A_ModuloToState}, "A_MODULOTOSTATE"}, + {{A_LavafallRocks}, "A_LAVAFALLROCKS"}, + {{A_LavafallLava}, "A_LAVAFALLLAVA"}, + {{A_FallingLavaCheck}, "A_FALLINGLAVACHECK"}, + {{A_FireShrink}, "A_FIRESHRINK"}, + {{A_SpawnPterabytes}, "A_SPAWNPTERABYTES"}, + {{A_PterabyteHover}, "A_PTERABYTEHOVER"}, + {{A_RolloutSpawn}, "A_ROLLOUTSPAWN"}, + {{A_RolloutRock}, "A_ROLLOUTROCK"}, {{NULL}, "NONE"}, // This NULL entry must be the last in the list @@ -4618,6 +4626,22 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_CANARIVOREGAS_7", "S_CANARIVOREGAS_8", + // Pyre Fly + "S_PYREFLY_FLY", + "S_PYREFLY_BURN", + "S_PYREFIRE1", + "S_PYREFIRE2", + + // Pterabyte + "S_PTERABYTESPAWNER", + "S_PTERABYTEWAYPOINT", + "S_PTERABYTE_FLY1", + "S_PTERABYTE_FLY2", + "S_PTERABYTE_FLY3", + "S_PTERABYTE_FLY4", + "S_PTERABYTE_SWOOPDOWN", + "S_PTERABYTE_SWOOPUP", + // Boss Explosion "S_BOSSEXPLODE", @@ -5894,6 +5918,28 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FLAMEJETFLAMEB2", "S_FLAMEJETFLAMEB3", + // Lavafall + "S_LAVAFALL_DORMANT", + "S_LAVAFALL_TELL", + "S_LAVAFALL_SHOOT", + "S_LAVAFALL_LAVA1", + "S_LAVAFALL_LAVA2", + "S_LAVAFALL_LAVA3", + "S_LAVAFALLROCK", + + // Rollout Rock + "S_ROLLOUTSPAWN", + "S_ROLLOUTROCK", + + // RVZ scenery + "S_BIGFERNLEAF", + "S_BIGFERN1", + "S_BIGFERN2", + "S_JUNGLEPALM", + "S_TORCHFLOWER", + "S_WALLVINE_LONG", + "S_WALLVINE_SHORT", + // Trapgoyles "S_TRAPGOYLE", "S_TRAPGOYLE_CHECK", @@ -6634,6 +6680,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SPLISH8", "S_SPLISH9", + // Lava splish + "S_LAVASPLISH", + // added water splash "S_SPLASH1", "S_SPLASH2", @@ -7284,6 +7333,11 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_UNIBALL", // Unidus Ball "MT_CANARIVORE", // Canarivore "MT_CANARIVORE_GAS", // Canarivore gas + "MT_PYREFLY", // Pyre Fly + "MT_PYREFLY_FIRE", // Pyre Fly fire + "MT_PTERABYTESPAWNER", // Pterabyte spawner + "MT_PTERABYTEWAYPOINT", // Pterabyte waypoint + "MT_PTERABYTE", // Pterabyte // Generic Boss Items "MT_BOSSEXPLODE", @@ -7629,6 +7683,20 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_FLAMEJETFLAMEB", // Blade's flame + "MT_LAVAFALL", + "MT_LAVAFALL_LAVA", + "MT_LAVAFALLROCK", + + "MT_ROLLOUTSPAWN", + "MT_ROLLOUTROCK", + + "MT_BIGFERNLEAF", + "MT_BIGFERN", + "MT_JUNGLEPALM", + "MT_TORCHFLOWER", + "MT_WALLVINE_LONG", + "MT_WALLVINE_SHORT", + // Dark City Scenery // Egg Rock Scenery @@ -7798,6 +7866,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_RAIN", // Rain "MT_SNOWFLAKE", // Snowflake "MT_SPLISH", // Water splish! + "MT_LAVASPLISH", // Lava splish! "MT_SMOKE", "MT_SMALLBUBBLE", // small bubble "MT_MEDIUMBUBBLE", // medium bubble @@ -8623,6 +8692,8 @@ struct { {"CR_ROPEHANG",CR_ROPEHANG}, {"CR_MACESPIN",CR_MACESPIN}, {"CR_MINECART",CR_MINECART}, + {"CR_ROLLOUT", CR_ROLLOUT}, + {"CR_PTERABYTE",CR_PTERABYTE}, // Ring weapons (ringweapons_t) // Useful for A_GiveWeapon diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index c76b1d296..f4637ff7f 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -180,6 +180,8 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_UNID &lspr[NOLIGHT], // SPR_CANA &lspr[NOLIGHT], // SPR_CANG + &lspr[NOLIGHT], // SPR_PYRE + &lspr[NOLIGHT], // SPR_PTER // Generic Boos Items &lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes @@ -260,6 +262,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_WSPB &lspr[NOLIGHT], // SPR_STPT &lspr[NOLIGHT], // SPR_BMNE + &lspr[NOLIGHT], // SPR_PUMI // Monitor Boxes &lspr[NOLIGHT], // SPR_MSTV @@ -377,6 +380,10 @@ light_t *t_lspr[NUMSPRITES] = // Red Volcano Scenery &lspr[REDBALL_L], // SPR_FLME &lspr[REDBALL_L], // SPR_DFLM + &lspr[NOLIGHT], // SPR_LFAL + &lspr[NOLIGHT], // SPR_JPLA + &lspr[NOLIGHT], // SPR_TFLO + &lspr[NOLIGHT], // SPR_WVIN // Dark City Scenery @@ -476,6 +483,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_RAIN &lspr[NOLIGHT], // SPR_SNO1 &lspr[NOLIGHT], // SPR_SPLH + &lspr[NOLIGHT], // SPR_LSPL &lspr[NOLIGHT], // SPR_SPLA &lspr[NOLIGHT], // SPR_SMOK &lspr[NOLIGHT], // SPR_BUBL diff --git a/src/info.c b/src/info.c index 17bd19e8a..dd5338ef0 100644 --- a/src/info.c +++ b/src/info.c @@ -68,6 +68,8 @@ char sprnames[NUMSPRITES + 1][5] = "UNID", // Unidus "CANA", // Canarivore "CANG", // Canarivore gas + "PYRE", // Pyre Fly + "PTER", // Pterabyte // Generic Boss Items "JETF", // Boss jet fumes @@ -149,6 +151,7 @@ char sprnames[NUMSPRITES + 1][5] = "WSPB", // Wall spike base "STPT", // Starpost "BMNE", // Big floating mine + "PUMI", // Rollout Rock // Monitor Boxes "MSTV", // MiSc TV sprites @@ -271,6 +274,10 @@ char sprnames[NUMSPRITES + 1][5] = // Red Volcano Scenery "FLME", // Flame jet "DFLM", // Blade's flame + "LFAL", // Lavafall + "JPLA", // Jungle palm + "TFLO", // Torch flower + "WVIN", // Wall vines // Dark City Scenery @@ -370,6 +377,7 @@ char sprnames[NUMSPRITES + 1][5] = "RAIN", // Rain "SNO1", // Snowflake "SPLH", // Water Splish + "LSPL", // Lava Splish "SPLA", // Water Splash "SMOK", "BUBL", // Bubble @@ -1185,6 +1193,22 @@ state_t states[NUMSTATES] = {SPR_CANG, 0|FF_TRANS80, 10, {NULL}, 0, 0, S_CANARIVOREGAS_8}, // S_CANARIVOREGAS_7 {SPR_CANG, 0|FF_TRANS90, 10, {NULL}, 0, 0, S_NULL}, // S_CANARIVOREGAS_8 + // Pyre Fly + {SPR_PYRE, FF_ANIMATE, -1, {NULL}, 3, 2, S_NULL}, // S_PYREFLY_FLY + {SPR_PYRE, 4|FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 3, 2, S_NULL}, // S_PYREFLY_BURN + {SPR_FLAM, FF_FULLBRIGHT, 10, {NULL}, 0, 0, S_PYREFIRE2}, // S_PYREFIRE1 + {SPR_FLAM, 1|FF_FULLBRIGHT, 10, {A_FireShrink}, 0, 16, S_NULL}, // S_PYREFIRE2 + + // Pterabyte + {SPR_NULL, 0, -1, {A_SpawnPterabytes}, 0, 0, S_PTERABYTESPAWNER}, // S_PTERABYTESPAWNER + {SPR_NULL, 0, 1, {A_PterabyteHover}, 0, 0, S_PTERABYTEWAYPOINT}, // S_PTERABYTEWAYPOINT + {SPR_PTER, 0, 6, {NULL}, 0, 0, S_PTERABYTE_FLY2}, // S_PTERABYTE_FLY1 + {SPR_PTER, 1, 2, {NULL}, 0, 0, S_PTERABYTE_FLY3}, // S_PTERABYTE_FLY2 + {SPR_PTER, 2, 6, {NULL}, 0, 0, S_PTERABYTE_FLY4}, // S_PTERABYTE_FLY3 + {SPR_PTER, 3, 2, {NULL}, 0, 0, S_PTERABYTE_FLY1}, // S_PTERABYTE_FLY4 + {SPR_PTER, 4, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPDOWN}, // S_PTERABYTE_SWOOPDOWN + {SPR_PTER, 0, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPUP}, // S_PTERABYTE_SWOOPUP + // Boss Explosion {SPR_BOM2, FF_FULLBRIGHT|FF_ANIMATE, (5*7), {NULL}, 6, 5, S_NULL}, // S_BOSSEXPLODE @@ -2499,6 +2523,28 @@ state_t states[NUMSTATES] = {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40, 1, {A_MoveRelative}, 0, 7, S_FLAMEJETFLAMEB3}, // S_FLAMEJETFLAMEB2 {SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|FF_ANIMATE, (12*7), {NULL}, 7, 12, S_NULL}, // S_FLAMEJETFLAMEB3 + // Lavafall + {SPR_LFAL, 5, 1, {NULL}, 0, 0, S_LAVAFALL_DORMANT}, // S_LAVAFALL_DORMANT + {SPR_LFAL, 6|FF_ANIMATE, 4, {A_LavafallRocks}, 1, 2, S_LAVAFALL_TELL}, // S_LAVAFALL_TELL + {SPR_LFAL, 9|FF_FULLBRIGHT|FF_ANIMATE, 2, {A_LavafallLava}, 1, 1, S_LAVAFALL_SHOOT}, // S_LAVAFALL_SHOOT + {SPR_LFAL, FF_FULLBRIGHT, 1, {A_FallingLavaCheck}, 0, 0, S_LAVAFALL_LAVA2}, // S_LAVAFALL_LAVA1 + {SPR_LFAL, FF_FULLBRIGHT, 1, {A_FallingLavaCheck}, 0, 0, S_LAVAFALL_LAVA1}, // S_LAVAFALL_LAVA2 + {SPR_LFAL, 2|FF_FULLBRIGHT|FF_ANIMATE, 9, {NULL}, 2, 3, S_NULL}, // S_LAVAFALL_LAVA3 + {SPR_LFAL, 11|FF_ANIMATE|FF_RANDOMANIM, 12, {NULL}, 3, 3, S_LAVAFALLROCK}, // S_LAVAFALLROCK + + // Rollout Rock + {SPR_NULL, 0, 1, {A_RolloutSpawn}, 256*FRACUNIT, MT_ROLLOUTROCK, S_ROLLOUTSPAWN}, // S_ROLLOUTSPAWN + {SPR_PUMI, 0, 1, {A_RolloutRock}, 63*FRACUNIT/64, 7*FRACUNIT/10, S_ROLLOUTROCK}, // S_ROLLOUTROCK + + // RVZ scenery + {SPR_JPLA, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BIGFERNLEAF + {SPR_JPLA, 1, 1, {NULL}, 0, 0, S_BIGFERN2}, // S_BIGFERN1 + {SPR_JPLA, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BIGFERN2 + {SPR_JPLA, 2, -1, {NULL}, 0, 0, S_NULL}, // S_JUNGLEPALM + {SPR_TFLO, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_TORCHFLOWER}, // S_TORCHFLOWER + {SPR_WVIN, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_LONG + {SPR_WVIN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_SHORT + // Trapgoyles {SPR_GARG, 0, 67, {NULL}, 0, 0, S_TRAPGOYLE_CHECK}, // S_TRAPGOYLE {SPR_GARG, 0, 3, {NULL}, 0, 0, S_TRAPGOYLE_FIRE1}, // S_TRAPGOYLE_CHECK @@ -3246,6 +3292,9 @@ state_t states[NUMSTATES] = {SPR_SPLH, FF_TRANS50|7, 2, {NULL}, 0, 0, S_SPLISH9}, // S_SPLISH8 {SPR_SPLH, FF_TRANS50|8, 2, {NULL}, 0, 0, S_NULL}, // S_SPLISH9 + // Lava splish + {SPR_LSPL, FF_ANIMATE, 16, {NULL}, 7, 2, S_NULL}, // S_LAVASPLISH + // Water Splash {SPR_SPLA, FF_TRANS50 , 3, {NULL}, 0, 0, S_SPLASH2}, // S_SPLASH1 {SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3}, // S_SPLASH2 @@ -3557,7 +3606,7 @@ state_t states[NUMSTATES] = // Puma (Mario fireball) {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_START2}, // S_PUMA_START1 - {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_PlaySound}, sfx_s3k70, 1, S_PUMA_UP1}, // S_PUMA_START2 + {SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_PlaySound}, sfx_s3k70, 1 + (1<<16), S_PUMA_UP1}, // S_PUMA_START2 {SPR_PUMA, FF_FULLBRIGHT , 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP2}, // S_PUMA_UP1 {SPR_PUMA, FF_FULLBRIGHT|1, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP3}, // S_PUMA_UP2 {SPR_PUMA, FF_FULLBRIGHT|2, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP1}, // S_PUMA_UP3 @@ -5039,6 +5088,141 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_PYREFLY + 136, // doomednum + S_PYREFLY_FLY, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_PYREFLY_BURN, // meleestate + S_NULL, // missilestate + S_XPLD_FLICKY, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 1, // speed + 24*FRACUNIT, // radius + 34*FRACUNIT, // height + 0, // display offset + DMG_FIRE, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_SLIDEME, // flags + S_NULL // raisestate + }, + + { // MT_PYREFLY_FIRE + -1, // doomednum + S_PYREFIRE1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 24*FRACUNIT, // radius + 34*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOBLOCKMAP|MF_FIRE|MF_PAIN, // flags + S_NULL // raisestate + }, + + { // MT_PTERABYTESPAWNER + 135, // doomednum + S_PTERABYTESPAWNER, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPTHING|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_PTERABYTEWAYPOINT + -1, // doomednum + S_PTERABYTEWAYPOINT, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 4*FRACUNIT, // speed + 24*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_NOCLIPTHING|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_PTERABYTE + -1, // doomednum + S_PTERABYTE_FLY1, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_pscree, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_XPLD_FLICKY, // deathstate + S_NULL, // xdeathstate + sfx_pop, // deathsound + 4*FRACUNIT, // speed + 24*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_NOGRAVITY|MF_SLIDEME, // flags + S_NULL // raisestate + }, + { // MT_BOSSEXPLODE -1, // doomednum S_BOSSEXPLODE, // spawnstate @@ -12863,6 +13047,303 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_LAVAFALL + 1304, // doomednum + S_LAVAFALL_DORMANT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_lvfal1, // seesound + 8, // reactiontime + sfx_s3kd5l, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 30*FRACUNIT, // radius + 32*FRACUNIT, // height + 1, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOGRAVITY|MF_SPAWNCEILING, // flags + S_NULL // raisestate + }, + + { // MT_LAVAFALL_LAVA + -1, // doomednum + S_LAVAFALL_LAVA1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_LAVAFALL_LAVA3, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 30*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_PAIN|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_LAVAFALLROCK + -1, // doomednum + S_LAVAFALLROCK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_ROLLOUTSPAWN + 1305, // doomednum + S_ROLLOUTSPAWN, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 8*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SPAWNCEILING, // flags + S_NULL // raisestate + }, + + { // MT_ROLLOUTROCK + -1, // doomednum + S_ROLLOUTROCK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime (sets number of frames the rock cycles through) + sfx_None, // attacksound + S_NULL, // painstate + 12*TICRATE, // painchance (sets how long an unridden rock should last before disappearing - set to 0 to disable) + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 32*FRACUNIT, // speed + 30*FRACUNIT, // radius + 60*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_PUSHABLE|MF_SOLID|MF_SLIDEME, // flags + S_NULL // raisestate + }, + + { // MT_BIGFERNLEAF + -1, // doomednum + S_BIGFERNLEAF, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_BIGFERN + 1306, // doomednum + S_BIGFERN1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags + S_NULL // raisestate + }, + + { // MT_JUNGLEPALM + 1307, // doomednum + S_JUNGLEPALM, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 32*FRACUNIT, // radius + 48*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_TORCHFLOWER + 1308, // doomednum + S_TORCHFLOWER, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 14*FRACUNIT, // radius + 110*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_WALLVINE_LONG + 1309, // doomednum + S_WALLVINE_LONG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 1*FRACUNIT, // radius + 288*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP, // flags + S_NULL // raisestate + }, + + { // MT_WALLVINE_SHORT + 1310, // doomednum + S_WALLVINE_SHORT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 1*FRACUNIT, // radius + 288*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SCENERY|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP, // flags + S_NULL // raisestate + }, + { // MT_TRAPGOYLE 1500, // doomednum S_TRAPGOYLE, // spawnstate @@ -16728,6 +17209,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_LAVASPLISH + -1, // doomednum + S_LAVASPLISH, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 6*FRACUNIT, // radius + 1*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_SMOKE -1, // doomednum S_SMOKE1, // spawnstate diff --git a/src/info.h b/src/info.h index 024328be1..0502fd095 100644 --- a/src/info.h +++ b/src/info.h @@ -268,6 +268,14 @@ void A_SnapperThinker(); void A_SaloonDoorSpawn(); void A_MinecartSparkThink(); void A_ModuloToState(); +void A_LavafallRocks(); +void A_LavafallLava(); +void A_FallingLavaCheck(); +void A_FireShrink(); +void A_SpawnPterabytes(); +void A_PterabyteHover(); +void A_RolloutSpawn(); +void A_RolloutRock(); // ratio of states to sprites to mobj types is roughly 6 : 1 : 1 #define NUMMOBJFREESLOTS 512 @@ -316,6 +324,8 @@ typedef enum sprite SPR_UNID, // Unidus SPR_CANA, // Canarivore SPR_CANG, // Canarivore gas + SPR_PYRE, // Pyre Fly + SPR_PTER, // Pterabyte // Generic Boss Items SPR_JETF, // Boss jet fumes @@ -397,6 +407,7 @@ typedef enum sprite SPR_WSPB, // Wall spike base SPR_STPT, // Starpost SPR_BMNE, // Big floating mine + SPR_PUMI, // Rollout Rock // Monitor Boxes SPR_MSTV, // MiSc TV sprites @@ -519,6 +530,10 @@ typedef enum sprite // Red Volcano Scenery SPR_FLME, // Flame jet SPR_DFLM, // Blade's flame + SPR_LFAL, // Lavafall + SPR_JPLA, // Jungle palm + SPR_TFLO, // Torch flower + SPR_WVIN, // Wall vines // Dark City Scenery @@ -618,6 +633,7 @@ typedef enum sprite SPR_RAIN, // Rain SPR_SNO1, // Snowflake SPR_SPLH, // Water Splish + SPR_LSPL, // Lava Splish SPR_SPLA, // Water Splash SPR_SMOK, SPR_BUBL, // Bubble @@ -1334,6 +1350,22 @@ typedef enum state S_CANARIVOREGAS_7, S_CANARIVOREGAS_8, + // Pyre Fly + S_PYREFLY_FLY, + S_PYREFLY_BURN, + S_PYREFIRE1, + S_PYREFIRE2, + + // Pterabyte + S_PTERABYTESPAWNER, + S_PTERABYTEWAYPOINT, + S_PTERABYTE_FLY1, + S_PTERABYTE_FLY2, + S_PTERABYTE_FLY3, + S_PTERABYTE_FLY4, + S_PTERABYTE_SWOOPDOWN, + S_PTERABYTE_SWOOPUP, + // Boss Explosion S_BOSSEXPLODE, @@ -2610,6 +2642,28 @@ typedef enum state S_FLAMEJETFLAMEB2, S_FLAMEJETFLAMEB3, + // Lavafall + S_LAVAFALL_DORMANT, + S_LAVAFALL_TELL, + S_LAVAFALL_SHOOT, + S_LAVAFALL_LAVA1, + S_LAVAFALL_LAVA2, + S_LAVAFALL_LAVA3, + S_LAVAFALLROCK, + + // Rollout Rock + S_ROLLOUTSPAWN, + S_ROLLOUTROCK, + + // RVZ scenery + S_BIGFERNLEAF, + S_BIGFERN1, + S_BIGFERN2, + S_JUNGLEPALM, + S_TORCHFLOWER, + S_WALLVINE_LONG, + S_WALLVINE_SHORT, + // Trapgoyles S_TRAPGOYLE, S_TRAPGOYLE_CHECK, @@ -3350,6 +3404,9 @@ typedef enum state S_SPLISH8, S_SPLISH9, + // Lava Splish + S_LAVASPLISH, + // added water splash S_SPLASH1, S_SPLASH2, @@ -4022,6 +4079,11 @@ typedef enum mobj_type MT_UNIBALL, // Unidus Ball MT_CANARIVORE, // Canarivore MT_CANARIVORE_GAS, // Canarivore gas + MT_PYREFLY, // Pyre Fly + MT_PYREFLY_FIRE, // Pyre Fly fire + MT_PTERABYTESPAWNER, // Pterabyte spawner + MT_PTERABYTEWAYPOINT, // Pterabyte waypoint + MT_PTERABYTE, // Pterabyte // Generic Boss Items MT_BOSSEXPLODE, @@ -4367,6 +4429,20 @@ typedef enum mobj_type MT_FLAMEJETFLAMEB, // Blade's flame + MT_LAVAFALL, + MT_LAVAFALL_LAVA, + MT_LAVAFALLROCK, + + MT_ROLLOUTSPAWN, + MT_ROLLOUTROCK, + + MT_BIGFERNLEAF, + MT_BIGFERN, + MT_JUNGLEPALM, + MT_TORCHFLOWER, + MT_WALLVINE_LONG, + MT_WALLVINE_SHORT, + // Dark City Scenery // Egg Rock Scenery @@ -4536,6 +4612,7 @@ typedef enum mobj_type MT_RAIN, // Rain MT_SNOWFLAKE, // Snowflake MT_SPLISH, // Water splish! + MT_LAVASPLISH, // Lava splish! MT_SMOKE, MT_SMALLBUBBLE, // small bubble MT_MEDIUMBUBBLE, // medium bubble diff --git a/src/lua_baselib.c b/src/lua_baselib.c index a69e8a188..8f173e32e 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -816,15 +816,12 @@ static int lib_pCheckDeathPitCollide(lua_State *L) static int lib_pCheckSolidLava(lua_State *L) { - mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); //HUDSAFE INLEVEL - if (!mo) - return LUA_ErrInvalid(L, "mobj_t"); if (!rover) return LUA_ErrInvalid(L, "ffloor_t"); - lua_pushboolean(L, P_CheckSolidLava(mo, rover)); + lua_pushboolean(L, P_CheckSolidLava(rover)); return 1; } diff --git a/src/p_enemy.c b/src/p_enemy.c index 26b28b0c9..10251910e 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -298,6 +298,14 @@ void A_SnapperThinker(mobj_t *actor); void A_SaloonDoorSpawn(mobj_t *actor); void A_MinecartSparkThink(mobj_t *actor); void A_ModuloToState(mobj_t *actor); +void A_LavafallRocks(mobj_t *actor); +void A_LavafallLava(mobj_t *actor); +void A_FallingLavaCheck(mobj_t *actor); +void A_FireShrink(mobj_t *actor); +void A_SpawnPterabytes(mobj_t *actor); +void A_PterabyteHover(mobj_t *actor); +void A_RolloutSpawn(mobj_t *actor); +void A_RolloutRock(mobj_t *actor); //for p_enemy.c @@ -8413,8 +8421,8 @@ void A_ChangeAngleAbsolute(mobj_t *actor) // // var1 = sound # to play // var2: -// 0 = Play sound without an origin -// 1 = Play sound using calling object as origin +// lower 16 bits = If 1, play sound using calling object as origin. If 0, play sound without an origin +// upper 16 bits = If 1, do not play sound during preticker. // void A_PlaySound(mobj_t *actor) { @@ -8425,7 +8433,10 @@ void A_PlaySound(mobj_t *actor) return; #endif - S_StartSound(locvar2 ? actor : NULL, locvar1); + if (leveltime < 2 && (locvar2 >> 16)) + return; + + S_StartSound((locvar2 & 65535) ? actor : NULL, locvar1); } // Function: A_FindTarget @@ -12202,7 +12213,7 @@ void A_MineExplode(mobj_t *actor) #undef dist if (actor->watertop != INT32_MAX) - P_SpawnMobj(actor->x, actor->y, actor->watertop, MT_SPLISH); + P_SpawnMobj(actor->x, actor->y, actor->watertop, (actor->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH); } } @@ -14002,3 +14013,290 @@ void A_ModuloToState(mobj_t *actor) P_SetMobjState(actor, (locvar2)); modulothing++; } + +// Function: A_LavafallRocks +// +// Description: Spawn random rock particles. +// +// var1 = unused +// var2 = unused +// +void A_LavafallRocks(mobj_t *actor) +{ + UINT8 i; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_LavafallRocks", actor)) + return; +#endif + + // Don't spawn rocks unless a player is relatively close by. + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (1600 << FRACBITS)) + break; // Stop looking. + + if (i < MAXPLAYERS) + { + angle_t fa = (FixedAngle(P_RandomKey(360) << FRACBITS) >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t offset = P_RandomRange(4, 12) << FRACBITS; + fixed_t xoffs = FixedMul(FINECOSINE(fa), actor->radius + offset); + fixed_t yoffs = FixedMul(FINESINE(fa), actor->radius + offset); + P_SpawnMobjFromMobj(actor, xoffs, yoffs, 0, MT_LAVAFALLROCK); + } +} + +// Function: A_LavafallLava +// +// Description: Spawn lava from lavafall. +// +// var1 = unused +// var2 = unused +// +void A_LavafallLava(mobj_t *actor) +{ + mobj_t *lavafall; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_LavafallLava", actor)) + return; +#endif + + if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS))) + return; + + lavafall = P_SpawnMobjFromMobj(actor, 0, 0, -8*FRACUNIT, MT_LAVAFALL_LAVA); + lavafall->momz = -P_MobjFlip(actor)*25*FRACUNIT; +} + +// Function: A_FallingLavaCheck +// +// Description: If actor hits the ground or a water surface, enter the death animation. +// +// var1 = unused +// var2 = unused +// +void A_FallingLavaCheck(mobj_t *actor) +{ +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FallingLavaCheck", actor)) + return; +#endif + + if (actor->eflags & MFE_TOUCHWATER || P_IsObjectOnGround(actor)) + { + actor->flags = MF_NOGRAVITY|MF_NOCLIPTHING; + actor->momz = 0; + if (actor->eflags & MFE_TOUCHWATER) + actor->z = (actor->eflags & MFE_VERTICALFLIP) ? actor->waterbottom : actor->watertop; + P_SetMobjState(actor, actor->info->deathstate); + } +} + +// Function: A_FireShrink +// +// Description: Shrink the actor down to the specified scale at the specified speed. +// +// var1 = Scale to shrink to +// var2 = Shrinking speed +// +void A_FireShrink(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_FireShrink", actor)) + return; +#endif + + actor->destscale = locvar1; + actor->scalespeed = FRACUNIT/locvar2; +} + +// Function: A_SpawnPterabytes +// +// Description: Spawn Pterabytes around the actor in a circle. +// +// var1 = unused +// var2 = unused +// +void A_SpawnPterabytes(mobj_t *actor) +{ + mobj_t *waypoint, *ptera; + fixed_t c, s; + fixed_t rad = 280*FRACUNIT; + angle_t ang = 0; + angle_t interval, fa; + UINT8 amount = 1; + UINT8 i; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SpawnPterabytes", actor)) + return; +#endif + + if (actor->spawnpoint) + amount = actor->spawnpoint->extrainfo + 1; + + interval = FixedAngle(FRACUNIT*360/amount); + + for (i = 0; i < amount; i++) + { + fa = (ang >> ANGLETOFINESHIFT) & FINEMASK; + c = FINECOSINE(fa); + s = FINESINE(fa); + waypoint = P_SpawnMobjFromMobj(actor, FixedMul(c, rad), FixedMul(s, rad), 0, MT_PTERABYTEWAYPOINT); + waypoint->angle = ang + ANGLE_90; + P_SetTarget(&waypoint->tracer, actor); + ptera = P_SpawnMobjFromMobj(waypoint, 0, 0, 0, MT_PTERABYTE); + ptera->angle = waypoint->angle; + P_SetTarget(&ptera->tracer, waypoint); + ptera->extravalue1 = 0; + ang += interval; + } +} + +// Function: A_PterabyteHover +// +// Description: Hover in a circular fashion, bobbing up and down slightly. +// +// var1 = unused +// var2 = unused +// +void A_PterabyteHover(mobj_t *actor) +{ + angle_t ang, fa; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_PterabyteHover", actor)) + return; +#endif + + P_InstaThrust(actor, actor->angle, actor->info->speed); + actor->angle += ANG1; + actor->extravalue1 = (actor->extravalue1 + 3) % 360; + ang = actor->extravalue1*ANG1; + fa = (ang >> ANGLETOFINESHIFT) & FINEMASK; + actor->z += FINESINE(fa); +} +// Function: A_RolloutSpawn +// +// Description: Spawns a new Rollout Rock when the currently spawned rock is destroyed or moves far enough away. +// +// var1 = Distance currently spawned rock should travel before spawning a new one +// var2 = Object type to spawn +// +void A_RolloutSpawn(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RolloutSpawn", actor)) + return; +#endif + + if (!(actor->target) + || P_MobjWasRemoved(actor->target) + || P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) > locvar1) + { + actor->target = P_SpawnMobj(actor->x, actor->y, actor->z, locvar2); + actor->target->flags2 |= (actor->flags2 & (MF2_AMBUSH | MF2_OBJECTFLIP)) | MF2_SLIDEPUSH; + actor->target->eflags |= (actor->eflags & MFE_VERTICALFLIP); + + if (actor->target->flags2 & MF2_AMBUSH) + { + actor->target->color = SKINCOLOR_SUPERRUST3; + actor->target->colorized = true; + } + } +} + +// Function: A_RolloutRock +// +// Description: Thinker for Rollout Rock. +// +// var1 = Drag +// var2 = Vertical bobbing speed factor +// +void A_RolloutRock(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_RolloutRock", actor)) + return; +#endif + + UINT8 maxframes = actor->info->reactiontime; // number of frames the mobj cycles through + fixed_t pi = (22*FRACUNIT/7); + fixed_t circumference = FixedMul(2 * pi, actor->radius); // used to calculate when to change frame + fixed_t speed = P_AproxDistance(actor->momx, actor->momy), topspeed = FixedMul(actor->info->speed, actor->scale); + boolean inwater = actor->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER); + + actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves + + if (actor->threshold) + actor->threshold--; + + if (inwater && !(actor->flags2 & MF2_AMBUSH)) // buoyancy in water (or lava) + { + UINT8 flip = P_MobjFlip(actor); + fixed_t prevmomz = actor->momz; + actor->momz = FixedMul(actor->momz, locvar2); + actor->momz += flip * FixedMul(locvar2, actor->scale); + if (flip*prevmomz < 0 && flip*actor->momz >= 0 && !actor->threshold) + { + if (actor->eflags & MFE_UNDERWATER) + S_StartSound(actor, sfx_splash); + else if (!actor->threshold) + S_StartSound(actor, sfx_splish); + actor->threshold = max((topspeed - speed) >> FRACBITS, 8); + } + } + + if (speed > topspeed) // cap speed + { + actor->momx = FixedMul(FixedDiv(actor->momx, speed), topspeed); + actor->momy = FixedMul(FixedDiv(actor->momy, speed), topspeed); + } + + if (P_IsObjectOnGround(actor) || inwater) // apply drag to speed (compensates for lack of friction but also works in liquids) + { + actor->momx = FixedMul(actor->momx, locvar1); + actor->momy = FixedMul(actor->momy, locvar1); + } + + speed = P_AproxDistance(actor->momx, actor->momy); // recalculate speed for visual rolling + + if (speed < actor->scale >> 1) // stop moving if speed is insignificant + { + actor->momx = 0; + actor->momy = 0; + } + else if (speed > actor->scale) + { + actor->movecount = 1; // rock has moved; fuse should be set so we don't have a trillion rocks lying around + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); // set rock's angle to movement direction + actor->movefactor += speed; + if (actor->movefactor > circumference / maxframes) // if distance moved is enough to change frame, change it! + { + actor->reactiontime++; + actor->reactiontime %= maxframes; + actor->movefactor = 0; + } + } + + actor->frame = actor->reactiontime % maxframes; // set frame + + if (!(actor->flags & MF_PUSHABLE)) // if being ridden, don't disappear + actor->fuse = 0; + else if (!actor->fuse && actor->movecount == 1) // otherwise if rock has moved, set its fuse + actor->fuse = actor->info->painchance; + + if (actor->fuse && actor->fuse < 2*TICRATE) + actor->flags2 ^= MF2_DONTDRAW; + +} diff --git a/src/p_floor.c b/src/p_floor.c index 7887dc530..19b7611b8 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1778,6 +1778,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_RAIN: case MT_SNOWFLAKE: case MT_SPLISH: + case MT_LAVASPLISH: case MT_SMOKE: case MT_SMALLBUBBLE: case MT_MEDIUMBUBBLE: diff --git a/src/p_inter.c b/src/p_inter.c index 53b8c5906..d11fddcda 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -450,12 +450,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } } break; + case MT_PYREFLY: + if (special->extravalue2 == 2 && P_DamageMobj(player->mo, special, special, 1, DMG_FIRE)) + return; default: break; } if (P_PlayerCanDamage(player, special)) // Do you possess the ability to subdue the object? { + if (special->type == MT_PTERABYTE && special->target == player->mo && special->extravalue1 == 1) + return; // Can't hurt a Pterabyte if it's trying to pick you up + if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1)) { if (elementalpierce == 2) @@ -477,7 +483,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_TwinSpinRejuvenate(player, player->thokitem); } else + { + if (special->type == MT_PTERABYTE && special->target == player->mo) + return; // Don't hurt the player you're trying to grab + P_DamageMobj(toucher, special, special, 1, 0); + } return; } diff --git a/src/p_local.h b/src/p_local.h index 4a5865027..02f497850 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -303,7 +303,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover); boolean P_CheckDeathPitCollide(mobj_t *mo); -boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover); +boolean P_CheckSolidLava(ffloor_t *rover); void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype); mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type); diff --git a/src/p_map.c b/src/p_map.c index 43e9d0319..ac5459fed 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -490,6 +490,42 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) } } +static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera) +{ + if (player->powers[pw_carry] && players->powers[pw_carry] != CR_ROLLOUT) + return; + if (ptera->extravalue1 != 1) + return; // Not swooping + if (ptera->target != player->mo) + return; // Not swooping for you! + + if (player->spectator) + return; + + if ((player->mo->eflags & MFE_VERTICALFLIP) != (ptera->eflags & MFE_VERTICALFLIP)) + return; // Both should be in same gravity + + if (ptera->eflags & MFE_VERTICALFLIP) + { + if (ptera->ceilingz - (ptera->z + ptera->height) < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale)) + return; + } + else if (ptera->z - ptera->floorz < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale)) + return; // No room to pick up this guy! + + P_ResetPlayer(player); + P_SetTarget(&player->mo->tracer, ptera); + player->pflags &= ~PF_APPLYAUTOBRAKE; + player->powers[pw_carry] = CR_PTERABYTE; + S_StartSound(player->mo, sfx_s3k4a); + P_UnsetThingPosition(player->mo); + player->mo->x = ptera->x; + player->mo->y = ptera->y; + P_SetThingPosition(player->mo); + ptera->movefactor = 3*TICRATE; + ptera->watertop = ptera->waterbottom = ptera->cusval = 0; +} + static void P_DoTailsCarry(player_t *sonic, player_t *tails) { INT32 p; @@ -882,6 +918,15 @@ static boolean PIT_CheckThing(mobj_t *thing) } #endif + if (tmthing->type == MT_LAVAFALL_LAVA && (thing->type == MT_RING || thing->type == MT_REDTEAMRING || thing->type == MT_BLUETEAMRING || thing->type == MT_FLINGRING)) + { + //height check + if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !(thing->health)) + return true; + + P_KillMobj(thing, tmthing, tmthing, DMG_FIRE); + } + if (tmthing->type == MT_MINECART) { //height check @@ -918,6 +963,64 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } + if (thing->type == MT_ROLLOUTROCK && tmthing->player && tmthing->health) + { + if (tmthing->player->powers[pw_carry] == CR_ROLLOUT) + { + return true; + } + if ((thing->flags & MF_PUSHABLE) // not carrying a player + && (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something + && ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP)) + && (P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < (thing->radius)) + && (P_MobjFlip(tmthing)*tmthing->momz <= 0) + && ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2)) + || (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2)))) + { + thing->flags &= ~MF_PUSHABLE; // prevent riding player from applying pushable movement logic + thing->flags2 &= ~MF2_DONTDRAW; // don't leave the rock invisible if it was flashing prior to boarding + P_SetTarget(&thing->tracer, tmthing); + P_ResetPlayer(tmthing->player); + P_SetPlayerMobjState(tmthing, S_PLAY_WALK); + tmthing->player->powers[pw_carry] = CR_ROLLOUT; + P_SetTarget(&tmthing->tracer, thing); + P_SetObjectMomZ(thing, tmthing->momz, true); + return true; + } + } + else if (tmthing->type == MT_ROLLOUTROCK) + { + if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !thing->health) + return true; + + if (thing == tmthing->tracer) // don't collide with rider + return true; + + if (thing->flags & MF_SPRING) // bounce on springs + { + P_DoSpring(thing, tmthing); + return true; + } + else if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) == (MF_MONITOR|MF_SHOOTABLE) && !(tmthing->flags & MF_PUSHABLE)) // pop monitors while carrying a player + { + P_KillMobj(thing, tmthing, tmthing->tracer, 0); + return true; + } + + if (thing->type == tmthing->type // bounce against other rollout rocks + && (tmthing->momx || tmthing->momy || thing->momx || thing->momy)) + { + fixed_t tempmomx = thing->momx, tempmomy = thing->momy; + thing->momx = tmthing->momx; + thing->momy = tmthing->momy; + tmthing->momx = tempmomx; + tmthing->momy = tempmomy; + } + } + + if (thing->type == MT_PTERABYTE && tmthing->player) + P_DoPterabyteCarry(tmthing->player, thing); + if (thing->type == MT_TNTBARREL && tmthing->player) P_PlayerBarrelCollide(tmthing, thing); @@ -1965,7 +2068,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) continue; } - if (thing->player && (P_CheckSolidLava(thing, rover) || P_CanRunOnWater(thing->player, rover))) + if (thing->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(thing->player, rover))) ; else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)) ; @@ -3480,6 +3583,64 @@ stairstep: goto retry; } +static void P_CheckLavaWall(mobj_t *mo, sector_t *sec) +{ + ffloor_t *rover; + fixed_t topheight, bottomheight; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!(rover->flags & FF_SWIMMABLE)) + continue; + + if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 3) + continue; + + if (rover->master->flags & ML_BLOCKMONSTERS) + continue; + + topheight = +#ifdef ESLOPE + *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : +#endif + *rover->topheight; + + if (mo->eflags & MFE_VERTICALFLIP) + { + if (topheight < mo->z - mo->height) + continue; + } + else + { + if (topheight < mo->z) + continue; + } + + bottomheight = +#ifdef ESLOPE + *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : +#endif + *rover->bottomheight; + + if (mo->eflags & MFE_VERTICALFLIP) + { + if (bottomheight > mo->z) + continue; + } + else + { + if (bottomheight > mo->z + mo->height) + continue; + } + + P_DamageMobj(mo, NULL, NULL, 1, DMG_FIRE); + return; + } +} + // // P_SlideMove // The momx / momy move is bad, so try to slide @@ -3640,6 +3801,12 @@ retry: P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy, PT_ADDLINES, PTR_SlideTraverse); + if (bestslideline && mo->player && bestslideline->sidenum[1] != 0xffff) + { + sector_t *sec = P_PointOnLineSide(mo->x, mo->y, bestslideline) ? bestslideline->frontsector : bestslideline->backsector; + P_CheckLavaWall(mo, sec); + } + // Some walls are bouncy even if you're not if (bestslideline && bestslideline->flags & ML_BOUNCY) { diff --git a/src/p_maputl.c b/src/p_maputl.c index 45fc82fbf..22998c60e 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -662,7 +662,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) + if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover))) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) @@ -708,7 +708,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover))) + if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover))) ; else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) diff --git a/src/p_mobj.c b/src/p_mobj.c index 4e6684887..7fa51111d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2222,7 +2222,7 @@ void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype) topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); - if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should stand on lava or run on water + if (mo->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mo->player, rover))) // only the player should stand on lava or run on water ; else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only continue; @@ -2379,43 +2379,11 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) return false; } -boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover) +boolean P_CheckSolidLava(ffloor_t *rover) { - fixed_t topheight; - - I_Assert(mo != NULL); - I_Assert(!P_MobjWasRemoved(mo)); - - // not a lava block with solid planes - if (!(rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 - && !(rover->master->flags & ML_BLOCKMONSTERS))) - return false; - - // is solid from the sides - if (rover->master->flags & ML_EFFECT3) - return true; - - if (mo->eflags & MFE_VERTICALFLIP) - { - topheight = - #ifdef ESLOPE - *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : - #endif - *rover->bottomheight; - - if (mo->z+mo->height-mo->momz < topheight + FixedMul(16*FRACUNIT, mo->scale)) - return true; - return false; - } - - topheight = - #ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : - #endif - *rover->topheight; - - if (mo->z-mo->momz > topheight - FixedMul(16*FRACUNIT, mo->scale)) - return true; + if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 + && !(rover->master->flags & ML_BLOCKMONSTERS)) + return true; return false; } @@ -3350,7 +3318,7 @@ void P_MobjCheckWater(mobj_t *mobj) mobj->watertop = mobj->waterbottom = mobj->z - 1000*FRACUNIT; // Reset water state. - mobj->eflags &= ~(MFE_UNDERWATER|MFE_TOUCHWATER|MFE_GOOWATER); + mobj->eflags &= ~(MFE_UNDERWATER|MFE_TOUCHWATER|MFE_GOOWATER|MFE_TOUCHLAVA); for (rover = sector->ffloors; rover; rover = rover->next) { @@ -3391,16 +3359,18 @@ void P_MobjCheckWater(mobj_t *mobj) // Just touching the water? if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - height < bottomheight) || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + height > topheight)) - { mobj->eflags |= MFE_TOUCHWATER; - if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY)) - mobj->eflags |= MFE_GOOWATER; - } + // Actually in the water? if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - (height>>1) > bottomheight) || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + (height>>1) < topheight)) - { mobj->eflags |= MFE_UNDERWATER; + + if (mobj->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) + { + if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 3) + mobj->eflags |= MFE_TOUCHLAVA; + if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY)) mobj->eflags |= MFE_GOOWATER; } @@ -3487,14 +3457,15 @@ void P_MobjCheckWater(mobj_t *mobj) { // Spawn a splash mobj_t *splish; + mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; if (mobj->eflags & MFE_VERTICALFLIP) { - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[MT_SPLISH].height, mobj->scale), MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype); splish->flags2 |= MF2_OBJECTFLIP; splish->eflags |= MFE_VERTICALFLIP; } else - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); splish->destscale = mobj->scale; P_SetScale(splish, mobj->scale); } @@ -3522,14 +3493,15 @@ void P_MobjCheckWater(mobj_t *mobj) { // Spawn a splash mobj_t *splish; + mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; if (mobj->eflags & MFE_VERTICALFLIP) { - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[MT_SPLISH].height, mobj->scale), MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype); splish->flags2 |= MF2_OBJECTFLIP; splish->eflags |= MFE_VERTICALFLIP; } else - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); splish->destscale = mobj->scale; P_SetScale(splish, mobj->scale); } @@ -3545,6 +3517,8 @@ void P_MobjCheckWater(mobj_t *mobj) if (mobj->eflags & MFE_GOOWATER || wasingoo) S_StartSound(mobj, sfx_ghit); + else if (mobj->eflags & MFE_TOUCHLAVA) + S_StartSound(mobj, sfx_splash); else S_StartSound(mobj, sfx_splish); // And make a sound! @@ -4155,6 +4129,45 @@ void P_RainThinker(precipmobj_t *mobj) P_SetPrecipMobjState(mobj, S_SPLASH1); } +static void P_KillRingsInLava(mobj_t *mo) +{ + msecnode_t *node; + I_Assert(mo != NULL); + I_Assert(!P_MobjWasRemoved(mo)); + + // go through all sectors being touched by the ring + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (!node->m_sector) + break; + + if (node->m_sector->ffloors) + { + ffloor_t *rover; + fixed_t topheight, bottomheight; + + for (rover = node->m_sector->ffloors; rover; rover = rover->next) // go through all fofs in the sector + { + if (!(rover->flags & FF_EXISTS)) continue; // fof must be real + + if (!(rover->flags & FF_SWIMMABLE // fof must be water + && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3)) // fof must be lava water + continue; + + // find heights of FOF + topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); + bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); + + if (mo->z <= topheight && mo->z + mo->height >= bottomheight) // if ring touches it, KILL IT + { + P_KillMobj(mo, NULL, NULL, DMG_FIRE); + return; + } + } + } + } +} + static void P_RingThinker(mobj_t *mobj) { if (mobj->momx || mobj->momy) @@ -7063,6 +7076,16 @@ void P_HandleMinecartSegments(mobj_t *mobj) P_UpdateMinecartSegments(mobj); } +static void P_PyreFlyBurn(mobj_t *mobj, fixed_t hoffs, INT16 vrange, mobjtype_t mobjtype, fixed_t momz) +{ + angle_t fa = (FixedAngle(P_RandomKey(360)*FRACUNIT) >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t xoffs = FixedMul(FINECOSINE(fa), mobj->radius + hoffs); + fixed_t yoffs = FixedMul(FINESINE(fa), mobj->radius + hoffs); + fixed_t zoffs = P_RandomRange(-vrange, vrange)*FRACUNIT; + mobj_t *particle = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, zoffs, mobjtype); + particle->momz = momz; +} + // // P_MobjThinker // @@ -9137,13 +9160,17 @@ void P_MobjThinker(mobj_t *mobj) } break; case MT_RING: + case MT_REDTEAMRING: + case MT_BLUETEAMRING: + P_KillRingsInLava(mobj); + if (P_MobjWasRemoved(mobj)) + return; + /* FALLTHRU */ case MT_COIN: case MT_BLUESPHERE: case MT_BOMBSPHERE: case MT_NIGHTSCHIP: case MT_NIGHTSSTAR: - case MT_REDTEAMRING: - case MT_BLUETEAMRING: // No need to check water. Who cares? P_RingThinker(mobj); if (mobj->flags2 & MF2_NIGHTSPULL) @@ -9153,6 +9180,10 @@ void P_MobjThinker(mobj_t *mobj) return; // Flung items case MT_FLINGRING: + P_KillRingsInLava(mobj); + if (P_MobjWasRemoved(mobj)) + return; + /* FALLTHRU */ case MT_FLINGCOIN: case MT_FLINGBLUESPHERE: case MT_FLINGNIGHTSCHIP: @@ -9354,6 +9385,159 @@ void P_MobjThinker(mobj_t *mobj) } mobj->flags2 ^= MF2_DONTDRAW; break; + case MT_LAVAFALLROCK: + if (P_IsObjectOnGround(mobj)) + P_RemoveMobj(mobj); + break; + case MT_PYREFLY: + { + fixed_t hdist; + + mobj->extravalue1 = (mobj->extravalue1 + 3) % 360; + mobj->z += FINESINE(((mobj->extravalue1*ANG1) >> ANGLETOFINESHIFT) & FINEMASK); + + if (!(mobj->flags2 & MF2_BOSSNOTRAP)) + P_LookForPlayers(mobj, true, false, 1500*FRACUNIT); + + if (!mobj->target) + break; + + if (mobj->extravalue2 == 1) + P_PyreFlyBurn(mobj, 0, 20, MT_SMOKE, 4*FRACUNIT); + else if (mobj->extravalue2 == 2) + { + INT32 fireradius = min(100 - mobj->fuse, 52); + P_PyreFlyBurn(mobj, P_RandomRange(0, fireradius)*FRACUNIT, 20, MT_FLAMEPARTICLE, 4*FRACUNIT); + P_PyreFlyBurn(mobj, fireradius*FRACUNIT, 40, MT_PYREFLY_FIRE, 0); + } + + hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + + if (!(mobj->flags2 & MF2_BOSSNOTRAP) && hdist <= 450*FRACUNIT) + mobj->flags2 |= MF2_BOSSNOTRAP; + + if (!(mobj->flags2 & MF2_BOSSNOTRAP)) + break; + + if (hdist < 1000*FRACUNIT) + { + //Aim for player z position. If too close to floor/ceiling, aim just above/below them. + fixed_t destz = min(max(mobj->target->z, mobj->target->floorz + 70*FRACUNIT), mobj->target->ceilingz - 80*FRACUNIT - mobj->height); + fixed_t dist = P_AproxDistance(hdist, destz - mobj->z); + P_InstaThrust(mobj, R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y), 2*FRACUNIT); + mobj->momz = FixedMul(FixedDiv(destz - mobj->z, dist), 2*FRACUNIT); + } + else + { + mobj->momx = 0; + mobj->momy = 0; + mobj->momz = 0; + if (hdist >= 1500*FRACUNIT) + { + mobj->flags2 &= ~MF2_BOSSNOTRAP; + P_SetTarget(&mobj->target, NULL); + } + } + break; + } + case MT_PTERABYTE: + { + if (mobj->extravalue1 & 4) // Cooldown after grabbing + { + if (mobj->movefactor) + mobj->movefactor--; + else + { + P_SetTarget(&mobj->target, NULL); + mobj->extravalue1 &= 3; + } + } + + if ((mobj->extravalue1 & 3) == 0) // Hovering + { + fixed_t vdist, hdist, time; + fixed_t hspeed = 3*mobj->info->speed; + angle_t fa; + + var1 = 1; + var2 = 0; + A_CapeChase(mobj); + + if (mobj->target) + break; // Still carrying a player or in cooldown + + P_LookForPlayers(mobj, true, false, 256*FRACUNIT); + + if (!mobj->target) + break; + + if (mobj->target->player->powers[pw_flashing]) + { + P_SetTarget(&mobj->target, NULL); + break; + } + + vdist = mobj->z - mobj->target->z - mobj->target->height; + if (P_MobjFlip(mobj)*vdist <= 0) + { + P_SetTarget(&mobj->target, NULL); + break; + } + + hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + if (hdist > 450*FRACUNIT) + { + P_SetTarget(&mobj->target, NULL); + break; + } + + P_SetMobjState(mobj, S_PTERABYTE_SWOOPDOWN); + mobj->extravalue1++; + S_StartSound(mobj, mobj->info->attacksound); + time = FixedDiv(hdist, hspeed); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + fa = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK; + mobj->momx = FixedMul(FINECOSINE(fa), hspeed); + mobj->momy = FixedMul(FINESINE(fa), hspeed); + mobj->momz = -2*FixedDiv(vdist, time); + mobj->extravalue2 = -FixedDiv(mobj->momz, time); //Z accel + mobj->movecount = time >> FRACBITS; + mobj->reactiontime = mobj->movecount; + } + else if ((mobj->extravalue1 & 3) == 1) // Swooping + { + mobj->reactiontime--; + mobj->momz += mobj->extravalue2; + if (mobj->reactiontime) + break; + + if (mobj->state - states == S_PTERABYTE_SWOOPDOWN) + { + P_SetMobjState(mobj, S_PTERABYTE_SWOOPUP); + mobj->reactiontime = mobj->movecount; + } + else if (mobj->state - states == S_PTERABYTE_SWOOPUP) + { + P_SetMobjState(mobj, S_PTERABYTE_FLY1); + mobj->extravalue1++; + if (mobj->target && mobj->target->tracer != mobj) + P_SetTarget(&mobj->target, NULL); // Failed to grab the target + mobj->momx = mobj->momy = mobj->momz = 0; + } + } + else // Returning + { + var1 = 2*mobj->info->speed; + var2 = 1; + A_HomingChase(mobj); + if (P_AproxDistance(mobj->x - mobj->tracer->x, mobj->y - mobj->tracer->y) <= mobj->info->speed) + { + mobj->extravalue1 -= 2; + mobj->momx = mobj->momy = mobj->momz = 0; + } + } + break; + } case MT_SPINFIRE: if (mobj->flags & MF_NOGRAVITY) { @@ -9584,6 +9768,52 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s case MT_NIGHTSCORE: P_RemoveMobj(mobj); return; + case MT_LAVAFALL: + if (mobj->state - states == S_LAVAFALL_DORMANT) + { + mobj->fuse = 30; + P_SetMobjState(mobj, S_LAVAFALL_TELL); + S_StartSound(mobj, mobj->info->seesound); + } + else if (mobj->state - states == S_LAVAFALL_TELL) + { + mobj->fuse = 40; + P_SetMobjState(mobj, S_LAVAFALL_SHOOT); + S_StopSound(mobj); + S_StartSound(mobj, mobj->info->attacksound); + } + else + { + mobj->fuse = 30; + P_SetMobjState(mobj, S_LAVAFALL_DORMANT); + S_StopSound(mobj); + } + return; + case MT_PYREFLY: + if (mobj->health <= 0) + break; + + mobj->extravalue2 = (mobj->extravalue2 + 1) % 3; + if (mobj->extravalue2 == 0) + { + P_SetMobjState(mobj, mobj->info->spawnstate); + mobj->fuse = 100; + S_StopSound(mobj); + S_StartSound(mobj, sfx_s3k8c); + } + else if (mobj->extravalue2 == 1) + { + mobj->fuse = 50; + S_StartSound(mobj, sfx_s3ka3); + } + else + { + P_SetMobjState(mobj, mobj->info->meleestate); + mobj->fuse = 100; + S_StopSound(mobj); + S_StartSound(mobj, sfx_s3kc2l); + } + return; case MT_PLAYER: break; // don't remove default: @@ -10165,6 +10395,17 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) P_SetTarget(&mobj->tracer, P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID)); mobj->tracer->angle = mobj->angle + ANGLE_90; break; + case MT_TORCHFLOWER: + { + mobj_t *fire = P_SpawnMobjFromMobj(mobj, 0, 0, 46*FRACUNIT, MT_FLAME); + P_SetTarget(&mobj->target, fire); + break; + } + case MT_PYREFLY: + mobj->extravalue1 = (FixedHypot(mobj->x, mobj->y)/FRACUNIT) % 360; + mobj->extravalue2 = 0; + mobj->fuse = 100; + break; default: break; } @@ -12211,6 +12452,38 @@ ML_EFFECT5 : Don't stop thinking when too far away if (mthing->angle > 0) mobj->tics += mthing->angle; break; + case MT_LAVAFALL: + mobj->fuse = 30 + mthing->angle; + if (mthing->options & MTF_AMBUSH) + { + P_SetScale(mobj, 2*mobj->scale); + mobj->destscale = mobj->scale; + } + break; + case MT_PYREFLY: + //start on fire if Ambush flag is set, otherwise behave normally + if (mthing->options & MTF_AMBUSH) + { + P_SetMobjState(mobj, mobj->info->meleestate); + mobj->extravalue2 = 2; + S_StartSound(mobj, sfx_s3kc2l); + } + break; + case MT_BIGFERN: + { + angle_t angle = FixedAngle(mthing->angle << FRACBITS); + UINT8 j; + for (j = 0; j < 8; j++) + { + angle_t fa = (angle >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t xoffs = FINECOSINE(fa); + fixed_t yoffs = FINESINE(fa); + mobj_t *leaf = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, 0, MT_BIGFERNLEAF); + leaf->angle = angle; + angle += ANGLE_45; + } + break; + } default: break; } diff --git a/src/p_mobj.h b/src/p_mobj.h index a9d5244b0..94fcc2987 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -233,15 +233,17 @@ typedef enum MFE_VERTICALFLIP = 1<<5, // Goo water MFE_GOOWATER = 1<<6, + // The mobj is touching a lava block + MFE_TOUCHLAVA = 1<<7, // Mobj was already pushed this tic - MFE_PUSHED = 1<<7, + MFE_PUSHED = 1<<8, // Mobj was already sprung this tic - MFE_SPRUNG = 1<<8, + MFE_SPRUNG = 1<<9, // Platform movement - MFE_APPLYPMOMZ = 1<<9, + MFE_APPLYPMOMZ = 1<<10, // Compute and trigger on mobj angle relative to tracer // See Linedef Exec 457 (Track mobj angle to point) - MFE_TRACERANGLE = 1<<10, + MFE_TRACERANGLE = 1<<11, // free: to and including 1<<15 } mobjeflag_t; diff --git a/src/p_user.c b/src/p_user.c index a72a00a11..ff30778ee 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1031,6 +1031,17 @@ 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_ROLLOUT) + { + if (player->mo->tracer && !P_MobjWasRemoved(player->mo->tracer)) + { + player->mo->tracer->flags |= MF_PUSHABLE; + P_SetTarget(&player->mo->tracer->tracer, NULL); + } + P_SetTarget(&player->mo->tracer, NULL); + player->powers[pw_carry] = CR_NONE; + } + 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; @@ -3689,7 +3700,7 @@ static void P_DoTeeter(player_t *player) bottomheight = *rover->bottomheight; #endif - if (P_CheckSolidLava(player->mo, rover)) + if (P_CheckSolidLava(rover)) ; else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND)) continue; // intangible 3d floor @@ -4311,6 +4322,16 @@ void P_DoJump(player_t *player, boolean soundandstate) if (player->mo->ceilingz-player->mo->floorz <= player->mo->height-1) return; + if (player->powers[pw_carry] == CR_PTERABYTE) + { + S_StartSound(player->mo, sfx_s3kd7s); + player->mo->tracer->cusval += 10; + player->mo->tracer->watertop = P_RandomRange(-player->mo->tracer->cusval, player->mo->tracer->cusval) << (FRACBITS - 1); + player->mo->tracer->waterbottom = P_RandomRange(-player->mo->tracer->cusval, player->mo->tracer->cusval) << (FRACBITS - 1); + player->mo->tracer->cvmem = P_RandomRange(-player->mo->tracer->cusval, player->mo->tracer->cusval) << (FRACBITS - 1); + return; + } + // Jump this high. if (player->powers[pw_carry] == CR_PLAYER) { @@ -4324,6 +4345,8 @@ void P_DoJump(player_t *player, boolean soundandstate) { player->mo->momz = 9*FRACUNIT; player->powers[pw_carry] = CR_NONE; + player->mo->tracer->flags |= MF_PUSHABLE; + P_SetTarget(&player->mo->tracer->target, NULL); P_SetTarget(&player->mo->tracer, NULL); } else if (player->powers[pw_carry] == CR_ROPEHANG) @@ -4332,6 +4355,14 @@ void P_DoJump(player_t *player, boolean soundandstate) player->powers[pw_carry] = CR_NONE; P_SetTarget(&player->mo->tracer, NULL); } + else if (player->powers[pw_carry] == CR_ROLLOUT) + { + player->mo->momz = 9*FRACUNIT + player->mo->tracer->momz; + player->powers[pw_carry] = CR_NONE; + player->mo->tracer->flags |= MF_PUSHABLE; + P_SetTarget(&player->mo->tracer->tracer, NULL); + P_SetTarget(&player->mo->tracer, NULL); + } else if (player->mo->eflags & MFE_GOOWATER) { player->mo->momz = 7*FRACUNIT; @@ -7350,10 +7381,13 @@ static void P_NiGHTSMovement(player_t *player) && player->mo->z + player->mo->height - P_GetPlayerHeight(player) <= player->mo->waterbottom && player->mo->z + player->mo->height >= player->mo->waterbottom)) && player->speed > 9000 && leveltime % (TICRATE/7) == 0 && !player->spectator) { + mobjtype_t splishtype = (player->mo->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; mobj_t *water = P_SpawnMobj(player->mo->x, player->mo->y, - ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_SPLISH].height, player->mo->scale) : player->mo->watertop), MT_SPLISH); + ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[splishtype].height, player->mo->scale) : player->mo->watertop), splishtype); if (player->mo->eflags & MFE_GOOWATER) S_StartSound(water, sfx_ghit); + else if (player->mo->eflags & MFE_TOUCHLAVA) + S_StartSound(water, sfx_splash); else S_StartSound(water, sfx_wslap); if (player->mo->eflags & MFE_VERTICALFLIP) @@ -8115,10 +8149,13 @@ static void P_MovePlayer(player_t *player) && (player->speed > runspd || (player->pflags & PF_STARTDASH)) && leveltime % (TICRATE/7) == 0 && player->mo->momz == 0 && !(player->pflags & PF_SLIDING) && !player->spectator) { + mobjtype_t splishtype = (player->mo->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; mobj_t *water = P_SpawnMobj(player->mo->x - P_ReturnThrustX(NULL, player->mo->angle, player->mo->radius), player->mo->y - P_ReturnThrustY(NULL, player->mo->angle, player->mo->radius), - ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_SPLISH].height, player->mo->scale) : player->mo->watertop), MT_SPLISH); + ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[splishtype].height, player->mo->scale) : player->mo->watertop), splishtype); if (player->mo->eflags & MFE_GOOWATER) S_StartSound(water, sfx_ghit); + else if (player->mo->eflags & MFE_TOUCHLAVA) + S_StartSound(water, sfx_splash); else S_StartSound(water, sfx_wslap); if (player->mo->eflags & MFE_VERTICALFLIP) @@ -11240,6 +11277,8 @@ void P_PlayerThink(player_t *player) // deez New User eXperiences. { + angle_t diff = 0; + UINT8 factor; // Directionchar! // Camera angle stuff. if (player->exiting // no control, no modification @@ -11266,8 +11305,16 @@ void P_PlayerThink(player_t *player) /* FALLTHRU */ case CR_MINECART: case CR_GENERIC: + case CR_PTERABYTE: player->drawangle = player->mo->tracer->angle; break; + case CR_ROLLOUT: + if (cmd->forwardmove || cmd->sidemove) // only when you're pressing movement keys + { // inverse direction! + diff = ((player->mo->angle + R_PointToAngle2(0, 0, -cmd->forwardmove<sidemove<drawangle); + factor = 4; + } + break; /* -- in case we wanted to have the camera freely movable during zoom tubes case CR_ZOOMTUBE:*/ case CR_ROPEHANG: @@ -11288,9 +11335,6 @@ void P_PlayerThink(player_t *player) ; else { - angle_t diff; - UINT8 factor; - if (player->pflags & PF_SLIDING) { #if 0 // fun hydrocity style horizontal spin @@ -11326,15 +11370,15 @@ void P_PlayerThink(player_t *player) diff = (player->mo->angle - player->drawangle); factor = 8; } + } - if (diff) - { - if (diff > ANGLE_180) - diff = InvAngle(InvAngle(diff)/factor); - else - diff /= factor; - player->drawangle += diff; - } + if (diff) + { + if (diff > ANGLE_180) + diff = InvAngle(InvAngle(diff)/factor); + else + diff /= factor; + player->drawangle += diff; } // Autobrake! check ST_drawInput if you modify this @@ -11653,6 +11697,36 @@ void P_PlayerThink(player_t *player) }*/ } +// Checks if the mobj is above lava. Used by Pterabyte. +static boolean P_MobjAboveLava(mobj_t *mobj) +{ + sector_t *sector = mobj->subsector->sector; + + if (sector->ffloors) + { + ffloor_t *rover; + + for (rover = sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || GETSECSPECIAL(rover->master->frontsector->special, 1) != 3) + continue; + + if (mobj->eflags & MFE_VERTICALFLIP) + { + if (*rover->bottomheight <= mobj->ceilingz && *rover->bottomheight >= mobj->z) + return true; + } + else + { + if (*rover->topheight >= mobj->floorz && *rover->topheight <= mobj->z) + return true; + } + } + } + + return false; +} + // // P_PlayerAfterThink // @@ -11968,6 +12042,114 @@ void P_PlayerAfterThink(player_t *player) } break; } + case CR_ROLLOUT: + { + mobj_t *mo = player->mo, *rock = player->mo->tracer; + UINT8 walktics = mo->state->tics - P_GetPlayerControlDirection(player); + + if (!rock || P_MobjWasRemoved(rock)) + { + P_SetTarget(&player->mo->tracer, NULL); + player->powers[pw_carry] = CR_NONE; + break; + } + + if (player->cmd.forwardmove || player->cmd.sidemove) + { + rock->movedir = (player->cmd.angleturn << FRACBITS) + R_PointToAngle2(0, 0, player->cmd.forwardmove << FRACBITS, -player->cmd.sidemove << FRACBITS); + P_Thrust(rock, rock->movedir, rock->scale >> 1); + } + + mo->momx = rock->momx; + mo->momy = rock->momy; + mo->momz = 0; + + if (player->panim == PA_IDLE && (mo->momx || mo->momy)) + { + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + } + + if (player->panim == PA_WALK && mo->tics > walktics) + { + mo->tics = walktics; + } + + P_TeleportMove(player->mo, rock->x, rock->y, rock->z + rock->height); + break; + } + case CR_PTERABYTE: // being carried by a Pterabyte + { + mobj_t *ptera = player->mo->tracer; + mobj_t *spawnpoint = ptera->tracer->tracer; + player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14 * FRACUNIT, 10 * FRACUNIT)); + + if (ptera->health <= 0) + goto dropoff; + + if (P_MobjAboveLava(ptera) && ptera->movefactor <= 3*TICRATE - 10) + goto dropoff; + + if (player->mo->eflags & MFE_VERTICALFLIP) + { + if ((ptera->z + ptera->height + player->mo->height + FixedMul(FRACUNIT, player->mo->scale)) <= ptera->ceilingz + && (ptera->eflags & MFE_VERTICALFLIP)) // Reverse gravity check for the carrier - Flame + player->mo->z = ptera->z + ptera->height + FixedMul(FRACUNIT, player->mo->scale); + + if (ptera->ceilingz - ptera->z > spawnpoint->ceilingz - spawnpoint->z + 512*FRACUNIT && ptera->movefactor <= 3 * TICRATE - 10) + goto dropoff; + } + else + { + if ((ptera->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale)) >= ptera->floorz + && !(ptera->eflags & MFE_VERTICALFLIP)) // Correct gravity check for the carrier - Flame + player->mo->z = ptera->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale); + + if (ptera->z - ptera->floorz > spawnpoint->z - spawnpoint->floorz + 512 * FRACUNIT && ptera->movefactor <= 3 * TICRATE - 10) + goto dropoff; + } + + ptera->movefactor--; + if (!ptera->movefactor) + goto dropoff; + + if (ptera->cusval >= 50) + { + player->powers[pw_carry] = CR_NONE; + P_SetTarget(&player->mo->tracer, NULL); + P_KillMobj(ptera, player->mo, player->mo, 0); + player->mo->momz = 9*FRACUNIT; + player->pflags |= PF_APPLYAUTOBRAKE|PF_JUMPED|PF_THOKKED; + P_SetMobjState(player->mo, S_PLAY_ROLL); + break; + } + + if (ptera->cusval) + ptera->cusval--; + + P_TryMove(player->mo, ptera->x + ptera->watertop, ptera->y + ptera->waterbottom, true); + player->mo->z += ptera->cvmem; + player->mo->momx = ptera->momx; + player->mo->momy = ptera->momy; + player->mo->momz = ptera->momz; + + if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > player->mo->radius) + goto dropoff; + + ptera->watertop >>= 1; + ptera->waterbottom >>= 1; + ptera->cvmem >>= 1; + + if (player->mo->state-states != S_PLAY_FALL) + P_SetPlayerMobjState(player->mo, S_PLAY_FALL); + break; + + dropoff: + player->powers[pw_carry] = CR_NONE; + P_SetTarget(&player->mo->tracer, NULL); + ptera->movefactor = TICRATE; + ptera->extravalue1 |= 4; + break; + } default: break; } diff --git a/src/sounds.c b/src/sounds.c index 6940cd9ee..e5dfeec8a 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -218,6 +218,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"chuchu", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Train horn"}, {"bsnipe", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Home-run smash"}, {"sprong", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power spring"}, + {"lvfal1", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rumble"}, + {"pscree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "SCREE!"}, // Menu, interface {"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"}, @@ -504,7 +506,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s3k6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical damage"}, {"s3k6f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, - {"s3k70", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, + {"s3k70", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, {"s3k71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Basic Shield"}, {"s3k72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Movement"}, {"s3k73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"}, @@ -555,7 +557,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3ka0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"}, {"s3ka1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s3ka2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"}, - {"s3ka3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lift"}, + {"s3ka3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising charge"}, {"s3ka4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"}, {"s3ka5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"s3ka6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction fizzle"}, diff --git a/src/sounds.h b/src/sounds.h index e5568b59a..9f6e0bab6 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -267,6 +267,8 @@ typedef enum sfx_chuchu, sfx_bsnipe, sfx_sprong, + sfx_lvfal1, + sfx_pscree, // Menu, interface sfx_chchng,