From 23bdb14eda8196c49487178e076b96267c31f25c Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 27 Jun 2017 20:16:14 +0100 Subject: [PATCH 1/8] * Make maces use the x offset of their controlling linedef to set the stage in the cycle the mace should be at, instead of contributing to the tilt of the plane of the maces. * Make the noclimb flag of the mace-controlling linedef turn the mace types that have spiked balls on the ends to also have the middles of the chain be spiked, CEZ3 style. * Partake in some refactoring. https://cdn.discordapp.com/attachments/293238104096112641/329335623250870275/srb20026.png An image of both changes in action! --- src/p_enemy.c | 5 ++-- src/p_mobj.c | 77 +++++++++++++++++++++++++++------------------------ 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 4b8d14170..6c87ebb23 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5206,8 +5206,8 @@ void A_MaceRotate(mobj_t *actor) radius = FixedMul(actor->info->speed * actor->reactiontime, actor->target->scale); // Double the radius if the chain links are made up of maces. - if (actor->target->type == MT_AXIS && (actor->type == MT_SMALLMACE || actor->type == MT_BIGMACE)) - radius *= 2; + /*if (actor->target->type == MT_AXIS && (actor->type == MT_SMALLMACE || actor->type == MT_BIGMACE)) + radius *= 2;*/ // Axis offset for the axis. radius += actor->target->extravalue1; @@ -5261,7 +5261,6 @@ void A_MaceRotate(mobj_t *actor) actor->threshold += actor->target->lastlook; actor->threshold &= FINEMASK; - actor->target->health &= FINEMASK; fa = actor->threshold; v[0] = FixedMul(FINECOSINE(fa), radius); diff --git a/src/p_mobj.c b/src/p_mobj.c index e1ac9f714..e3feef294 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9775,10 +9775,10 @@ void P_SpawnMapThing(mapthing_t *mthing) case MT_HANGMACEPOINT: case MT_SPINMACEPOINT: { - fixed_t mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed; + fixed_t mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed, movecountset, thresholdset, radiusfactor = 1; mobjtype_t chainlink = MT_SMALLMACECHAIN; mobjtype_t macetype = MT_SMALLMACE; - boolean firsttime; + const boolean hazard = (mobj->type == MT_MACEPOINT || mobj->type == MT_SWINGMACEPOINT); mobj_t *spawnee; INT32 line; const size_t mthingi = (size_t)(mthing - mapthings); @@ -9820,66 +9820,71 @@ ML_NOCLIMB : Direction not controllable mobj->lastlook = mspeed << 4; mobj->movecount = mobj->lastlook; - mobj->health = (FixedAngle(mzspeed*FRACUNIT)>>ANGLETOFINESHIFT) + (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT); - mobj->threshold = (FixedAngle(mxspeed*FRACUNIT)>>ANGLETOFINESHIFT) + (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT); + mobj->health = (FixedAngle(((mzspeed+mstartangle)%360)*FRACUNIT)>>ANGLETOFINESHIFT); + mobj->threshold = (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT); mobj->movefactor = mobj->threshold; mobj->friction = mmaxspeed; - if (lines[line].flags & ML_NOCLIMB) - mobj->flags |= MF_SLIDEME; - - mobj->reactiontime = 0; - if (mthing->options & MTF_AMBUSH) { chainlink = MT_BIGMACECHAIN; macetype = MT_BIGMACE; } + if (lines[line].flags & ML_NOCLIMB) + { + if (hazard) + { + chainlink = macetype; + radiusfactor = 2; // Double the radius. + } + else + mobj->flags |= MF_SLIDEME; + } + + mobj->reactiontime = 0; + if (mthing->options & MTF_OBJECTSPECIAL) mobj->flags2 |= MF2_BOSSNOTRAP; // shut up maces. - if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SPINMACEPOINT) - firsttime = true; + if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SWINGMACEPOINT) + movecountset = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; else - { - firsttime = false; + movecountset = 0; + thresholdset = FixedAngle(((mxspeed + mstartangle)%360)*FRACUNIT)>>ANGLETOFINESHIFT; + + if (hazard) // outermost mace + { spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, macetype); P_SetTarget(&spawnee->target, mobj); - if (mobj->type == MT_SWINGMACEPOINT) - spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - else - spawnee->movecount = 0; + spawnee->movecount = movecountset; + spawnee->threshold = thresholdset; + spawnee->reactiontime = radiusfactor*(mlength+1); + } + else if (mlength) // outermost link + { + spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, chainlink); + P_SetTarget(&spawnee->target, mobj); - spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - spawnee->reactiontime = mlength+1; + spawnee->movecount = movecountset; + spawnee->threshold = thresholdset; + spawnee->reactiontime = radiusfactor*(mlength--); + + spawnee->flags2 |= MF2_AMBUSH; } while (mlength > 0) { spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, chainlink); - P_SetTarget(&spawnee->target, mobj); - if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SWINGMACEPOINT) - spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - else - spawnee->movecount = 0; - - spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - spawnee->reactiontime = mlength; - - if (firsttime) - { - // This is the outermost link in the chain - spawnee->flags2 |= MF2_AMBUSH; - firsttime = false; - } - - mlength--; + spawnee->movecount = movecountset; + spawnee->threshold = thresholdset; + spawnee->reactiontime = radiusfactor*(mlength--); } + break; } case MT_PARTICLEGEN: From 86f9b6d40949c9ef84248a987e41fa2f584b1350 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 27 Jun 2017 23:34:55 +0100 Subject: [PATCH 2/8] After discussions, flipping the flag that means you CAN'T turn the CEZ chains now means that when it's enabled, you CAN turn them. In order to get base game parity by default, rather than as an obscure option. --- src/p_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index 9ae79e5e2..36b8eddf7 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9989,7 +9989,7 @@ void P_PlayerAfterThink(player_t *player) else if (cmd->forwardmove < 0 && player->mo->tracer->target->lastlook > player->mo->tracer->target->movecount) player->mo->tracer->target->lastlook -= 2; - if (!(player->mo->tracer->target->flags & MF_SLIDEME) // Noclimb on chain parameters gives this + if ((player->mo->tracer->target->flags & MF_SLIDEME) // Noclimb on chain parameters gives this && !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode? { player->mo->tracer->target->health += cmd->sidemove; From a0fa548e8b6c1091e3c0058a55d17966e9238663 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 28 Jun 2017 14:55:48 +0100 Subject: [PATCH 3/8] * Make spinning (normal) maces play the activesound once per rotation, instead of once every 64 tics. * Make swinging (as opposed to spinning) maces play the activesound at the peak of their speed. * Decouple the tilt of all maces from the angle. * Improve DBG_GAMELOGIC message. * Refactor. --- src/p_enemy.c | 32 +++++++++++++++++++------------- src/p_mobj.c | 49 ++++++++++++++++++++++--------------------------- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 6c87ebb23..716b1a5ca 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5188,6 +5188,7 @@ void A_MaceRotate(mobj_t *actor) TVector v; TVector *res; fixed_t radius; + INT32 prevswing; #ifdef HAVE_BLUA if (LUA_CallAction("A_MaceRotate", actor)) return; @@ -5238,10 +5239,16 @@ void A_MaceRotate(mobj_t *actor) // Swinging Chain. if (actor->target->type == MT_HANGMACEPOINT || actor->target->type == MT_SWINGMACEPOINT) { - actor->movecount += actor->target->lastlook; - actor->movecount &= FINEMASK; + actor->threshold += actor->target->lastlook; + actor->threshold &= FINEMASK; - actor->threshold = FixedMul(FINECOSINE(actor->movecount), actor->target->lastlook << FRACBITS); + prevswing = actor->movecount; + actor->movecount = FixedMul(FINECOSINE(actor->threshold), actor->target->lastlook << FRACBITS); + + if ((actor->flags2 & MF2_AMBUSH) // at the end of the chain + && !(actor->target->flags2 & MF2_BOSSNOTRAP) // flag that makes 'em shut up on request + && ((prevswing > 0) != (actor->movecount > 0))) // just passed its lowest point + S_StartSound(actor, actor->info->activesound); v[0] = FRACUNIT; v[1] = 0; @@ -5249,7 +5256,7 @@ void A_MaceRotate(mobj_t *actor) v[3] = FRACUNIT; // Calculate the angle matrixes for the link. - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->threshold))); + res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->movecount))); M_Memcpy(&v, res, sizeof(v)); res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT)); M_Memcpy(&v, res, sizeof(v)); @@ -5257,15 +5264,18 @@ void A_MaceRotate(mobj_t *actor) // Rotating Chain. else { - angle_t fa; - + prevswing = actor->threshold; actor->threshold += actor->target->lastlook; actor->threshold &= FINEMASK; - fa = actor->threshold; - v[0] = FixedMul(FINECOSINE(fa), radius); + if ((actor->flags2 & MF2_AMBUSH) // at the end of the chain + && !(actor->target->flags2 & MF2_BOSSNOTRAP) // flag that makes 'em shut up on request + && (!(prevswing > (FINEMASK/2)) && (actor->threshold > (FINEMASK/2)))) // completed a full swing + S_StartSound(actor, actor->info->activesound); + + v[0] = FixedMul(FINECOSINE((angle_t)actor->threshold), radius); v[1] = 0; - v[2] = FixedMul(FINESINE(fa), radius); + v[2] = FixedMul(FINESINE((angle_t)actor->threshold), radius); v[3] = FRACUNIT; // Calculate the angle matrixes for the link. @@ -5281,10 +5291,6 @@ void A_MaceRotate(mobj_t *actor) actor->z += v[2]; P_SetThingPosition(actor); - - if (!(actor->target->flags2 & MF2_BOSSNOTRAP) // flag that makes maces shut up on request - && !(leveltime & 63) && (actor->type == MT_BIGMACE || actor->type == MT_SMALLMACE) && actor->target->type == MT_MACEPOINT) - S_StartSound(actor, actor->info->activesound); } // Function: A_SetFuse diff --git a/src/p_mobj.c b/src/p_mobj.c index e3feef294..3ff5bfab5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9775,9 +9775,10 @@ void P_SpawnMapThing(mapthing_t *mthing) case MT_HANGMACEPOINT: case MT_SPINMACEPOINT: { - fixed_t mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed, movecountset, thresholdset, radiusfactor = 1; + fixed_t mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed, thresholdset, radiusfactor = 1; mobjtype_t chainlink = MT_SMALLMACECHAIN; mobjtype_t macetype = MT_SMALLMACE; + mobjtype_t firsttype; const boolean hazard = (mobj->type == MT_MACEPOINT || mobj->type == MT_SWINGMACEPOINT); mobj_t *spawnee; INT32 line; @@ -9793,10 +9794,12 @@ void P_SpawnMapThing(mapthing_t *mthing) return; } /* -No deaf - small mace -Deaf - big mace +No deaf - small +Deaf - big -ML_NOCLIMB : Direction not controllable +ML_NOCLIMB : +SPINMACEPOINT - Direction not controllable +MACEPOINT, SWINGMACEPOINT - Chain links are replaced with maces */ mlength = abs(lines[line].dx >> FRACBITS); mspeed = abs(lines[line].dy >> FRACBITS); @@ -9809,18 +9812,18 @@ ML_NOCLIMB : Direction not controllable mxspeed %= 360; mzspeed %= 360; - CONS_Debug(DBG_GAMELOGIC, "Mace Chain (mapthing #%s):\n" + CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n" "Length is %d\n" "Speed is %d\n" - "Xspeed is %d\n" - "Zspeed is %d\n" - "startangle is %d\n" - "maxspeed is %d\n", + "Phase is %d\n" + "Angle is %d\n" + "Tilt is %d\n" + "Max. speed is %d\n", sizeu1(mthingi), mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed); mobj->lastlook = mspeed << 4; mobj->movecount = mobj->lastlook; - mobj->health = (FixedAngle(((mzspeed+mstartangle)%360)*FRACUNIT)>>ANGLETOFINESHIFT); + mobj->health = (FixedAngle(mzspeed*FRACUNIT)>>ANGLETOFINESHIFT); mobj->threshold = (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT); mobj->movefactor = mobj->threshold; mobj->friction = mmaxspeed; @@ -9844,31 +9847,24 @@ ML_NOCLIMB : Direction not controllable mobj->reactiontime = 0; - if (mthing->options & MTF_OBJECTSPECIAL) + if (!mspeed || mthing->options & MTF_OBJECTSPECIAL) mobj->flags2 |= MF2_BOSSNOTRAP; // shut up maces. - if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SWINGMACEPOINT) - movecountset = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - else - movecountset = 0; - - thresholdset = FixedAngle(((mxspeed + mstartangle)%360)*FRACUNIT)>>ANGLETOFINESHIFT; + thresholdset = FixedAngle(mxspeed*FRACUNIT)>>ANGLETOFINESHIFT; if (hazard) // outermost mace { - spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, macetype); - P_SetTarget(&spawnee->target, mobj); - - spawnee->movecount = movecountset; - spawnee->threshold = thresholdset; - spawnee->reactiontime = radiusfactor*(mlength+1); + firsttype = macetype; + mlength++; } - else if (mlength) // outermost link + else + firsttype = chainlink; + + if (mlength) // outermost mace/link { - spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, chainlink); + spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, firsttype); P_SetTarget(&spawnee->target, mobj); - spawnee->movecount = movecountset; spawnee->threshold = thresholdset; spawnee->reactiontime = radiusfactor*(mlength--); @@ -9880,7 +9876,6 @@ ML_NOCLIMB : Direction not controllable spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, chainlink); P_SetTarget(&spawnee->target, mobj); - spawnee->movecount = movecountset; spawnee->threshold = thresholdset; spawnee->reactiontime = radiusfactor*(mlength--); } From 370d9c3176a80e126a5294f0c51f8db50eca7ff4 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 2 Jul 2017 15:11:09 +0100 Subject: [PATCH 4/8] Hooh boy. **** * MF2_MACEROTATE. Apply to any object. Replaces the indiscriminate spamming of A_MaceRotate each tic. **** * Mace point mapthings have been slightly modified. - MTF_AMBUSH: bigger luke theory (has no effect on custom mace, different effect on spring mace) - MTF_OBJECTFLIP: flips the objects, but nothing else - just so it doesn't look out of place in gravflip sections - MTF_OBJECTSPECIAL: keeps it from attempting to play swinging sounds - angle: tag of controlling linedef - parameter: number of "spokes" minus one - for example, a parameter of 2 results in 3 equidistant maces rotating around the same point. **** * Mace linedefs have been significantly revamped. - line dx: number of chain links - line dy: speed (in FU) - frontside floor height: Pitch (in degrees; how much it "tilts" over - Yaw influences the axis it's tilting on) - frontside ceiling height: Yaw (in degrees; rotation of entire thing on xy plane) - frontside x offset: Phase (in degrees; how far it is through the rotation cycle) - frontside y offset: Max speed (in FU; if less than speed, set to speed*2) - backside floor height: Pinch (in degrees; 0 if no backside; essentially makes rotation conical instead of wheel-like) - backside ceiling height: Roll (in degrees; 0 if no backside; rotates on the axis of the spinning - identical to Phase for spinning maces, but useful for rotating swinging maces as opposed to just offsetting them) - backside x offset: Number of "antispokes" (0 if no backside; makes that many spokes not exist so you can put another mace/chain type in there instead; for combo mace/chain instead turns them into chains directly) - backside y offset: Width (in number of extra chains per side; 0 if no backside; creates a "skiprope" arrangement) ---- - ML_NOCLIMB: for chains and chain-mace combos, allow for player control of yaw through strafe keys - ML_EFFECT1: replacing the seperate mapthings, this makes a mace type swing instead of spin. - ML_EFFECT2: for all spokes of the mace wheel ending in maces, make the chains out of the mace type (inverted for firebars) - ML_EFFECT3: spawn a bonus mace type at the center(s) of rotation - ML_EFFECT4: don't clip inside ground **** * Mapthing 1104 represents both spinning and swinging maces from prior versions of SRB2. * Mapthing 1105 has gone from being a swinging mace variant to a combination of chains and maces in a single unit, provided the number of "spokes" is greater than one. * Mapthing 1105 has gone from being a swinging chain variant to a vertical spring-on-a-ball-on-a-chain. Yellow by default, apply MTF_AMBUSH to turn into a red spring. * Mapthing 1107 represents both spinning and swinging chains from prior versions of SRB2. * Mapthing 1108 is completely untouched except to port over 2.1's functionality to the new backend. * Mapthing 1109 is a Mario castle-level style firebar. This inverts the functionality of ML_EFFECT2 on the tagged linedef. * Mapthing 1110 is a free slot should we want to implement another type of base-game mace. * Mapthing 1111 is a custom mace. Use the linedef's frontside texture slots to identify a macetype mobjtype, then use the backside texture slots to identify a linktype mobjtype (defaults to MT_NULL if no backside). **** Whooh. Requires new patch.dta for sprites. --- src/dehacked.c | 72 +++++-- src/hardware/hw_light.c | 4 + src/info.c | 278 ++++++++++++++++++++++---- src/info.h | 75 +++++-- src/p_enemy.c | 161 ++------------- src/p_inter.c | 3 +- src/p_mobj.c | 419 +++++++++++++++++++++++++++++++++------- src/p_mobj.h | 1 + src/p_setup.c | 1 + src/p_user.c | 12 +- 10 files changed, 753 insertions(+), 273 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index aa6f4f7f9..82f19e81b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1826,7 +1826,6 @@ static actionpointer_t actionpointers[] = {{A_CapeChase}, "A_CAPECHASE"}, {{A_RotateSpikeBall}, "A_ROTATESPIKEBALL"}, {{A_SlingAppear}, "A_SLINGAPPEAR"}, - {{A_MaceRotate}, "A_MACEROTATE"}, {{A_UnidusBall}, "A_UNIDUSBALL"}, {{A_RockSpawn}, "A_ROCKSPAWN"}, {{A_SetFuse}, "A_SETFUSE"}, @@ -5248,18 +5247,62 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SLING1", "S_SLING2", - // CEZ Small Mace Chain + // CEZ maces and chains "S_SMALLMACECHAIN", - - // CEZ Big Mace Chain "S_BIGMACECHAIN", - - // CEZ Small Mace "S_SMALLMACE", - - // CEZ Big Mace "S_BIGMACE", + // Yellow spring on a ball + "S_YELLOWSPRINGBALL", + "S_YELLOWSPRINGBALL2", + "S_YELLOWSPRINGBALL3", + "S_YELLOWSPRINGBALL4", + "S_YELLOWSPRINGBALL5", + + // Red spring on a ball + "S_REDSPRINGBALL", + "S_REDSPRINGBALL2", + "S_REDSPRINGBALL3", + "S_REDSPRINGBALL4", + "S_REDSPRINGBALL5", + + // Small Firebar + "S_SMALLFIREBAR1", + "S_SMALLFIREBAR2", + "S_SMALLFIREBAR3", + "S_SMALLFIREBAR4", + "S_SMALLFIREBAR5", + "S_SMALLFIREBAR6", + "S_SMALLFIREBAR7", + "S_SMALLFIREBAR8", + "S_SMALLFIREBAR9", + "S_SMALLFIREBAR10", + "S_SMALLFIREBAR11", + "S_SMALLFIREBAR12", + "S_SMALLFIREBAR13", + "S_SMALLFIREBAR14", + "S_SMALLFIREBAR15", + "S_SMALLFIREBAR16", + + // Big Firebar + "S_BIGFIREBAR1", + "S_BIGFIREBAR2", + "S_BIGFIREBAR3", + "S_BIGFIREBAR4", + "S_BIGFIREBAR5", + "S_BIGFIREBAR6", + "S_BIGFIREBAR7", + "S_BIGFIREBAR8", + "S_BIGFIREBAR9", + "S_BIGFIREBAR10", + "S_BIGFIREBAR11", + "S_BIGFIREBAR12", + "S_BIGFIREBAR13", + "S_BIGFIREBAR14", + "S_BIGFIREBAR15", + "S_BIGFIREBAR16", + "S_CEZFLOWER1", // Big Tumbleweed @@ -6587,14 +6630,20 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_FLAMEPARTICLE", "MT_EGGSTATUE", // Eggman Statue "MT_MACEPOINT", // Mace rotation point - "MT_SWINGMACEPOINT", // Mace swinging point - "MT_HANGMACEPOINT", // Hangable mace chain - "MT_SPINMACEPOINT", // Spin/Controllable mace chain + "MT_CHAINMACEPOINT", // Combination of chains and maces point + "MT_SPRINGBALLPOINT", // Spring ball point + "MT_CHAINPOINT", // Mace chain "MT_HIDDEN_SLING", // Spin mace chain (activatable) + "MT_FIREBARPOINT", // Firebar + "MT_CUSTOMMACEPOINT", // Custom mace "MT_SMALLMACECHAIN", // Small Mace Chain "MT_BIGMACECHAIN", // Big Mace Chain "MT_SMALLMACE", // Small Mace "MT_BIGMACE", // Big Mace + "MT_YELLOWSPRINGBALL", // Yellow spring on a ball + "MT_REDSPRINGBALL", // Red spring on a ball + "MT_SMALLFIREBAR", // Small Firebar + "MT_BIGFIREBAR", // Big Firebar "MT_CEZFLOWER", // Arid Canyon Scenery @@ -6947,6 +6996,7 @@ static const char *const MOBJFLAG2_LIST[] = { "AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH "LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) "SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) + "MACEROTATE", // Thinker calls P_MaceRotate around tracer NULL }; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index a49a788e6..aa5548f34 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -316,6 +316,10 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_BMCH &lspr[NOLIGHT], // SPR_SMCE &lspr[NOLIGHT], // SPR_BMCE + &lspr[NOLIGHT], // SPR_YSPB + &lspr[NOLIGHT], // SPR_RSPB + &lspr[REDBALL_L], // SPR_SFBR + &lspr[REDBALL_L], // SPR_BFBR // Arid Canyon Scenery &lspr[NOLIGHT], // SPR_BTBL diff --git a/src/info.c b/src/info.c index 9e779acb0..5b57bfab0 100644 --- a/src/info.c +++ b/src/info.c @@ -204,6 +204,10 @@ char sprnames[NUMSPRITES + 1][5] = "BMCH", // Big Mace Chain "SMCE", // Small Mace "BMCE", // Big Mace + "YSPB", // Yellow spring on a ball + "RSPB", // Red spring on a ball + "SFBR", // Small Firebar + "BFBR", // Big Firebar // Arid Canyon Scenery "BTBL", // Big tumbleweed @@ -1804,13 +1808,13 @@ state_t states[NUMSTATES] = {SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZCHAIN // Flame - {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20, 3, {A_FlameParticle}, 3, 0, S_FLAME2}, // S_FLAME1 - {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|1, 3, {NULL}, 0, 0, S_FLAME3}, // S_FLAME2 - {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|2, 3, {A_FlameParticle}, 3, 0, S_FLAME4}, // S_FLAME3 - {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|3, 3, {NULL}, 0, 0, S_FLAME5}, // S_FLAME4 - {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|4, 3, {A_FlameParticle}, 3, 0, S_FLAME6}, // S_FLAME5 - {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|5, 3, {NULL}, 0, 0, S_FLAME1}, // S_FLAME6 - {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS10|6, 24, {NULL}, 0, 0, S_NULL}, // S_FLAMEPARTICLE + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME2}, // S_FLAME1 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|1, 3, {NULL}, 0, 0 , S_FLAME3}, // S_FLAME2 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|2, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME4}, // S_FLAME3 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|3, 3, {NULL}, 0, 0 , S_FLAME5}, // S_FLAME4 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|4, 3, {A_FlameParticle}, 3, FRACUNIT/2, S_FLAME6}, // S_FLAME5 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|5, 3, {NULL}, 0, 0 , S_FLAME1}, // S_FLAME6 + {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS10|6, 24, {NULL}, 0, 0 , S_NULL}, // S_FLAMEPARTICLE {SPR_FLAM, FF_FULLBRIGHT|FF_TRANS20|FF_ANIMATE, -1, {NULL}, 5, 3, S_FLAME2}, // S_FLAMEREST @@ -1821,31 +1825,75 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, -1, {NULL}, 0, 0, S_SLING2}, // S_SLING1 {SPR_NULL, 0, -1, {A_SlingAppear}, 0, 0, S_NULL}, // S_SLING2 - // Small Mace Chain - {SPR_SMCH, 0, 1, {A_MaceRotate}, 0, 0, S_SMALLMACECHAIN}, // S_SMALLMACECHAIN + // CEZ maces and chains + {SPR_SMCH, 0, -1, {NULL}, 0, 0, S_SMALLMACECHAIN}, // S_SMALLMACECHAIN + {SPR_BMCH, 0, -1, {NULL}, 0, 0, S_BIGMACECHAIN}, // S_BIGMACECHAIN + {SPR_SMCE, 0, -1, {NULL}, 0, 0, S_SMALLMACE}, // S_SMALLMACE + {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_BIGMACE}, // S_BIGMACE - // Big Mace Chain - {SPR_BMCH, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACECHAIN}, // S_BIGMACECHAIN + // Yellow spring on a ball + {SPR_YSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRINGBALL + {SPR_YSPB, 4, 4, {A_Pain}, 0, 0, S_YELLOWSPRINGBALL3}, // S_YELLOWSPRINGBALL2 + {SPR_YSPB, 3, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL4}, // S_YELLOWSPRINGBALL3 + {SPR_YSPB, 2, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL5}, // S_YELLOWSPRINGBALL4 + {SPR_YSPB, 1, 1, {NULL}, 0, 0, S_YELLOWSPRINGBALL}, // S_YELLOWSPRINGBALL5 - // Small Mace - {SPR_SMCE, 0, 1, {A_MaceRotate}, 0, 0, S_SMALLMACE}, // S_SMALLMACE + // Red spring on a ball + {SPR_RSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDSPRINGBALL + {SPR_RSPB, 4, 4, {A_Pain}, 0, 0, S_REDSPRINGBALL3}, // S_REDSPRINGBALL2 + {SPR_RSPB, 3, 1, {NULL}, 0, 0, S_REDSPRINGBALL4}, // S_REDSPRINGBALL3 + {SPR_RSPB, 2, 1, {NULL}, 0, 0, S_REDSPRINGBALL5}, // S_REDSPRINGBALL4 + {SPR_RSPB, 1, 1, {NULL}, 0, 0, S_REDSPRINGBALL}, // S_REDSPRINGBALL5 - // Big Mace - {SPR_BMCE, 0, 1, {A_MaceRotate}, 0, 0, S_BIGMACE}, // S_BIGMACE + // Small Firebar + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR2}, // S_SMALLFIREBAR1 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 1, 1, {NULL}, 0, 0, S_SMALLFIREBAR3}, // S_SMALLFIREBAR2 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 2, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR4}, // S_SMALLFIREBAR3 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 3, 1, {NULL}, 0, 0, S_SMALLFIREBAR5}, // S_SMALLFIREBAR4 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 4, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR6}, // S_SMALLFIREBAR5 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 5, 1, {NULL}, 0, 0, S_SMALLFIREBAR7}, // S_SMALLFIREBAR6 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 6, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR8}, // S_SMALLFIREBAR7 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 7, 1, {NULL}, 0, 0, S_SMALLFIREBAR9}, // S_SMALLFIREBAR8 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 8, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR10}, // S_SMALLFIREBAR9 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20| 9, 1, {NULL}, 0, 0, S_SMALLFIREBAR11}, // S_SMALLFIREBAR10 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|10, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR12}, // S_SMALLFIREBAR11 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|11, 1, {NULL}, 0, 0, S_SMALLFIREBAR13}, // S_SMALLFIREBAR12 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|12, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR14}, // S_SMALLFIREBAR13 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|13, 1, {NULL}, 0, 0, S_SMALLFIREBAR15}, // S_SMALLFIREBAR14 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|14, 1, {A_FlameParticle}, 3, FRACUNIT/3, S_SMALLFIREBAR16}, // S_SMALLFIREBAR15 + {SPR_SFBR, FF_FULLBRIGHT|FF_TRANS20|15, 1, {NULL}, 0, 0, S_SMALLFIREBAR1}, // S_SMALLFIREBAR16 + + // Big Firebar + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR2}, // S_BIGFIREBAR1 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 1, 1, {NULL}, 0, 0, S_BIGFIREBAR3}, // S_BIGFIREBAR2 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 2, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR4}, // S_BIGFIREBAR3 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 3, 1, {NULL}, 0, 0, S_BIGFIREBAR5}, // S_BIGFIREBAR4 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 4, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR6}, // S_BIGFIREBAR5 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 5, 1, {NULL}, 0, 0, S_BIGFIREBAR7}, // S_BIGFIREBAR6 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 6, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR8}, // S_BIGFIREBAR7 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 7, 1, {NULL}, 0, 0, S_BIGFIREBAR9}, // S_BIGFIREBAR8 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 8, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR10}, // S_BIGFIREBAR9 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20| 9, 1, {NULL}, 0, 0, S_BIGFIREBAR11}, // S_BIGFIREBAR10 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|10, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR12}, // S_BIGFIREBAR11 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|11, 1, {NULL}, 0, 0, S_BIGFIREBAR13}, // S_BIGFIREBAR12 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|12, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR14}, // S_BIGFIREBAR13 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|13, 1, {NULL}, 0, 0, S_BIGFIREBAR15}, // S_BIGFIREBAR14 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|14, 1, {A_FlameParticle}, 3, FRACUNIT/2, S_BIGFIREBAR16}, // S_BIGFIREBAR15 + {SPR_BFBR, FF_FULLBRIGHT|FF_TRANS20|15, 1, {NULL}, 0, 0, S_BIGFIREBAR1}, // S_BIGFIREBAR16 // CEZ Flower {SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER1 // Big Tumbleweed - {SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED - {SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2}, // S_BIGTUMBLEWEED_ROLL1 - {SPR_BTBL, 1, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL3}, // S_BIGTUMBLEWEED_ROLL2 - {SPR_BTBL, 2, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL4}, // S_BIGTUMBLEWEED_ROLL3 - {SPR_BTBL, 3, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL5}, // S_BIGTUMBLEWEED_ROLL4 - {SPR_BTBL, 4, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL6}, // S_BIGTUMBLEWEED_ROLL5 - {SPR_BTBL, 5, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL7}, // S_BIGTUMBLEWEED_ROLL6 - {SPR_BTBL, 6, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL8}, // S_BIGTUMBLEWEED_ROLL7 - {SPR_BTBL, 7, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL1}, // S_BIGTUMBLEWEED_ROLL8 + {SPR_BTBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BIGTUMBLEWEED + {SPR_BTBL, 0, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL2}, // S_BIGTUMBLEWEED_ROLL1 + {SPR_BTBL, 1, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL3}, // S_BIGTUMBLEWEED_ROLL2 + {SPR_BTBL, 2, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL4}, // S_BIGTUMBLEWEED_ROLL3 + {SPR_BTBL, 3, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL5}, // S_BIGTUMBLEWEED_ROLL4 + {SPR_BTBL, 4, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL6}, // S_BIGTUMBLEWEED_ROLL5 + {SPR_BTBL, 5, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL7}, // S_BIGTUMBLEWEED_ROLL6 + {SPR_BTBL, 6, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL8}, // S_BIGTUMBLEWEED_ROLL7 + {SPR_BTBL, 7, 5, {NULL}, 0, 0, S_BIGTUMBLEWEED_ROLL1}, // S_BIGTUMBLEWEED_ROLL8 // Little Tumbleweed {SPR_STBL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LITTLETUMBLEWEED @@ -8504,7 +8552,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_SWINGMACEPOINT + { // MT_CHAINMACEPOINT 1105, // doomednum S_INVISIBLE, // spawnstate 1000, // spawnhealth @@ -8531,7 +8579,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_HANGMACEPOINT + { // MT_SPRINGBALLPOINT 1106, // doomednum S_INVISIBLE, // spawnstate 1000, // spawnhealth @@ -8558,7 +8606,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_SPINMACEPOINT + { // MT_CHAINPOINT 1107, // doomednum S_INVISIBLE, // spawnstate 1000, // spawnhealth @@ -8578,7 +8626,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 128*FRACUNIT, // radius 1*FRACUNIT, // height 0, // display offset - 200, // mass + 10000, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags @@ -8612,6 +8660,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_FIREBARPOINT + 1109, // doomednum + S_INVISIBLE, // 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 + 10*FRACUNIT, // speed + 128*FRACUNIT, // radius + 1*FRACUNIT, // height + 0, // display offset + 200, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + + { // MT_CUSTOMMACEPOINT + 1111, // doomednum + S_INVISIBLE, // 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 + 10*FRACUNIT, // speed + 128*FRACUNIT, // radius + 1*FRACUNIT, // height + 0, // display offset + 200, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + { // MT_SMALLMACECHAIN -1, // doomednum S_SMALLMACECHAIN, // spawnstate @@ -8635,7 +8737,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags + MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags S_NULL // raisestate }, @@ -8662,7 +8764,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 100, // mass 1, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_SPECIAL|MF_NOCLIPHEIGHT, // flags + MF_SCENERY|MF_SPECIAL|MF_NOGRAVITY, // flags S_NULL // raisestate }, @@ -8685,11 +8787,11 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 24*FRACUNIT, // speed 17*FRACUNIT, // radius 34*FRACUNIT, // height - 0, // display offset + 1, // display offset 100, // mass 1, // damage sfx_mswing, // activesound - MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags S_NULL // raisestate }, @@ -8712,11 +8814,119 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 48*FRACUNIT, // speed 34*FRACUNIT, // radius 68*FRACUNIT, // height - 0, // display offset + 1, // display offset 100, // mass 1, // damage sfx_mswing, // activesound - MF_PAIN|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + MF_SCENERY|MF_PAIN|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_YELLOWSPRINGBALL + -1, // doomednum + S_YELLOWSPRINGBALL, // spawnstate + 1000, // spawnhealth + S_YELLOWSPRINGBALL2, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_spring, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 24*FRACUNIT, // speed + 17*FRACUNIT, // radius + 34*FRACUNIT, // height + 1, // display offset + 20*FRACUNIT, // mass + 0, // damage + sfx_mswing, // activesound + MF_SCENERY|MF_SOLID|MF_SPRING|MF_NOGRAVITY, // flags + S_YELLOWSPRINGBALL2 // raisestate + }, + + { // MT_REDSPRINGBALL + -1, // doomednum + S_REDSPRINGBALL, // spawnstate + 1000, // spawnhealth + S_REDSPRINGBALL2, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_spring, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 24*FRACUNIT, // speed + 17*FRACUNIT, // radius + 34*FRACUNIT, // height + 1, // display offset + 32*FRACUNIT, // mass + 0, // damage + sfx_mswing, // activesound + MF_SCENERY|MF_SOLID|MF_SPRING|MF_NOGRAVITY, // flags + S_REDSPRINGBALL2 // raisestate + }, + + { // MT_SMALLFIREBAR + -1, // doomednum + S_SMALLFIREBAR1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + MT_FLAMEPARTICLE, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 24*FRACUNIT, // speed + 17*FRACUNIT, // radius + 34*FRACUNIT, // height + 0, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SCENERY|MF_PAIN|MF_FIRE|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_BIGFIREBAR + -1, // doomednum + S_BIGFIREBAR1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + MT_FLAMEPARTICLE, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 48*FRACUNIT, // speed + 34*FRACUNIT, // radius + 68*FRACUNIT, // height + 1, // display offset + 100, // mass + 1, // damage + sfx_None, // activesound + MF_SCENERY|MF_PAIN|MF_FIRE|MF_NOGRAVITY, // flags S_NULL // raisestate }, diff --git a/src/info.h b/src/info.h index 75484081e..9eaa8bad0 100644 --- a/src/info.h +++ b/src/info.h @@ -84,7 +84,6 @@ void A_DetonChase(); // Deton Chaser void A_CapeChase(); // Fake little Super Sonic cape void A_RotateSpikeBall(); // Spike ball rotation void A_SlingAppear(); -void A_MaceRotate(); void A_UnidusBall(); void A_RockSpawn(); void A_SetFuse(); @@ -410,6 +409,10 @@ typedef enum sprite SPR_BMCH, // Big Mace Chain SPR_SMCE, // Small Mace SPR_BMCE, // Big Mace + SPR_YSPB, // Yellow spring on a ball + SPR_RSPB, // Red spring on a ball + SPR_SFBR, // Small Firebar + SPR_BFBR, // Big Firebar // Arid Canyon Scenery SPR_BTBL, // Big tumbleweed @@ -2029,18 +2032,62 @@ typedef enum state S_SLING1, S_SLING2, - // CEZ Small Mace Chain + // CEZ maces and chains S_SMALLMACECHAIN, - - // CEZ Big Mace Chain S_BIGMACECHAIN, - - // CEZ Small Mace S_SMALLMACE, - - // CEZ Big Mace S_BIGMACE, + // Yellow spring on a ball + S_YELLOWSPRINGBALL, + S_YELLOWSPRINGBALL2, + S_YELLOWSPRINGBALL3, + S_YELLOWSPRINGBALL4, + S_YELLOWSPRINGBALL5, + + // Red spring on a ball + S_REDSPRINGBALL, + S_REDSPRINGBALL2, + S_REDSPRINGBALL3, + S_REDSPRINGBALL4, + S_REDSPRINGBALL5, + + // Small Firebar + S_SMALLFIREBAR1, + S_SMALLFIREBAR2, + S_SMALLFIREBAR3, + S_SMALLFIREBAR4, + S_SMALLFIREBAR5, + S_SMALLFIREBAR6, + S_SMALLFIREBAR7, + S_SMALLFIREBAR8, + S_SMALLFIREBAR9, + S_SMALLFIREBAR10, + S_SMALLFIREBAR11, + S_SMALLFIREBAR12, + S_SMALLFIREBAR13, + S_SMALLFIREBAR14, + S_SMALLFIREBAR15, + S_SMALLFIREBAR16, + + // Big Firebar + S_BIGFIREBAR1, + S_BIGFIREBAR2, + S_BIGFIREBAR3, + S_BIGFIREBAR4, + S_BIGFIREBAR5, + S_BIGFIREBAR6, + S_BIGFIREBAR7, + S_BIGFIREBAR8, + S_BIGFIREBAR9, + S_BIGFIREBAR10, + S_BIGFIREBAR11, + S_BIGFIREBAR12, + S_BIGFIREBAR13, + S_BIGFIREBAR14, + S_BIGFIREBAR15, + S_BIGFIREBAR16, + S_CEZFLOWER1, // Big Tumbleweed @@ -3387,14 +3434,20 @@ typedef enum mobj_type MT_FLAMEPARTICLE, MT_EGGSTATUE, // Eggman Statue MT_MACEPOINT, // Mace rotation point - MT_SWINGMACEPOINT, // Mace swinging point - MT_HANGMACEPOINT, // Hangable mace chain - MT_SPINMACEPOINT, // Spin/Controllable mace chain + MT_CHAINMACEPOINT, // Combination of chains and maces point + MT_SPRINGBALLPOINT, // Spring ball point + MT_CHAINPOINT, // Mace chain MT_HIDDEN_SLING, // Spin mace chain (activatable) + MT_FIREBARPOINT, // Firebar + MT_CUSTOMMACEPOINT, // Custom mace MT_SMALLMACECHAIN, // Small Mace Chain MT_BIGMACECHAIN, // Big Mace Chain MT_SMALLMACE, // Small Mace MT_BIGMACE, // Big Mace + MT_YELLOWSPRINGBALL, // Yellow spring on a ball + MT_REDSPRINGBALL, // Red spring on a ball + MT_SMALLFIREBAR, // Small Firebar + MT_BIGFIREBAR, // Big Firebar MT_CEZFLOWER, // Arid Canyon Scenery diff --git a/src/p_enemy.c b/src/p_enemy.c index 716b1a5ca..f7dbcb621 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -137,7 +137,6 @@ void A_DetonChase(mobj_t *actor); void A_CapeChase(mobj_t *actor); void A_RotateSpikeBall(mobj_t *actor); void A_SlingAppear(mobj_t *actor); -void A_MaceRotate(mobj_t *actor); void A_UnidusBall(mobj_t *actor); void A_RockSpawn(mobj_t *actor); void A_SetFuse(mobj_t *actor); @@ -5142,15 +5141,12 @@ void A_SlingAppear(mobj_t *actor) actor->movefactor = actor->threshold; actor->friction = 128; - actor->flags |= MF_SLIDEME; - while (mlength > 0) { spawnee = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLMACECHAIN); P_SetTarget(&spawnee->target, actor); - spawnee->movecount = 0; spawnee->threshold = 0; spawnee->reactiontime = mlength; @@ -5165,134 +5161,6 @@ void A_SlingAppear(mobj_t *actor) } } -// -// Function: A_MaceRotate -// -// Spins an object around its target, or, swings it from side to side. -// -// var1 = unused -// var2 = unused -// -// So NOBODY forgets: -// actor-> -// threshold - X tilt -// movecount - Z tilt -// reactiontime - link # in the chain (1 is closest) -// lastlook - speed -// friction - top speed -// movedir - current angle holder -// extravalue1 - smoothly move link into place -// -void A_MaceRotate(mobj_t *actor) -{ - TVector v; - TVector *res; - fixed_t radius; - INT32 prevswing; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MaceRotate", actor)) - return; -#endif - - // Target was removed. - if (!actor->target) - { - P_RemoveMobj(actor); - return; - } - - P_UnsetThingPosition(actor); - - // Radius of the link's rotation. - radius = FixedMul(actor->info->speed * actor->reactiontime, actor->target->scale); - - // Double the radius if the chain links are made up of maces. - /*if (actor->target->type == MT_AXIS && (actor->type == MT_SMALLMACE || actor->type == MT_BIGMACE)) - radius *= 2;*/ - - // Axis offset for the axis. - radius += actor->target->extravalue1; - - // Smoothly move the link into position. - if (actor->extravalue1) - { - radius = FixedMul(radius, FixedDiv(actor->extravalue1, 100)); - actor->extravalue1 += 1; - if (actor->extravalue1 >= 100) - actor->extravalue1 = 0; - } - - actor->x = actor->target->x; - actor->y = actor->target->y; - actor->z = actor->target->z; - - // Cut the height to align the link with the axis. - if (actor->type == MT_SMALLMACECHAIN || actor->type == MT_BIGMACECHAIN) - actor->z -= actor->height/4; - else - actor->z -= actor->height/2; - - // Set the top speed for the link if it happens to be over that speed. - if (actor->target->lastlook > actor->target->friction) - actor->target->lastlook = actor->target->friction; - - // Swinging Chain. - if (actor->target->type == MT_HANGMACEPOINT || actor->target->type == MT_SWINGMACEPOINT) - { - actor->threshold += actor->target->lastlook; - actor->threshold &= FINEMASK; - - prevswing = actor->movecount; - actor->movecount = FixedMul(FINECOSINE(actor->threshold), actor->target->lastlook << FRACBITS); - - if ((actor->flags2 & MF2_AMBUSH) // at the end of the chain - && !(actor->target->flags2 & MF2_BOSSNOTRAP) // flag that makes 'em shut up on request - && ((prevswing > 0) != (actor->movecount > 0))) // just passed its lowest point - S_StartSound(actor, actor->info->activesound); - - v[0] = FRACUNIT; - v[1] = 0; - v[2] = -radius; - v[3] = FRACUNIT; - - // Calculate the angle matrixes for the link. - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->movecount))); - M_Memcpy(&v, res, sizeof(v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT)); - M_Memcpy(&v, res, sizeof(v)); - } - // Rotating Chain. - else - { - prevswing = actor->threshold; - actor->threshold += actor->target->lastlook; - actor->threshold &= FINEMASK; - - if ((actor->flags2 & MF2_AMBUSH) // at the end of the chain - && !(actor->target->flags2 & MF2_BOSSNOTRAP) // flag that makes 'em shut up on request - && (!(prevswing > (FINEMASK/2)) && (actor->threshold > (FINEMASK/2)))) // completed a full swing - S_StartSound(actor, actor->info->activesound); - - v[0] = FixedMul(FINECOSINE((angle_t)actor->threshold), radius); - v[1] = 0; - v[2] = FixedMul(FINESINE((angle_t)actor->threshold), radius); - v[3] = FRACUNIT; - - // Calculate the angle matrixes for the link. - res = VectorMatrixMultiply(v, *RotateXMatrix(actor->target->threshold << ANGLETOFINESHIFT)); - M_Memcpy(&v, res, sizeof(v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT)); - M_Memcpy(&v, res, sizeof(v)); - } - - // Add on the appropriate distances to the actor's co-ordinates. - actor->x += v[0]; - actor->y += v[1]; - actor->z += v[2]; - - P_SetThingPosition(actor); -} - // Function: A_SetFuse // // Description: Sets the actor's fuse timer if not set already. May also change state when fuse reaches the last tic, otherwise by default the actor will die or disappear. (Replaces A_SnowBall) @@ -10796,26 +10664,33 @@ void A_FlickyFlutter(mobj_t *actor) // Description: Creates the mobj's painchance at a random position around the object's radius. // // var1 = momz of particle. +// var2 = chance of particle spawn // void A_FlameParticle(mobj_t *actor) { mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance); + fixed_t rad, hei; + mobj_t *particle; INT32 locvar1 = var1; + INT32 locvar2 = var2; #ifdef HAVE_BLUA if (LUA_CallAction("A_FlameParticle", actor)) return; #endif - if (type) - { - fixed_t rad = 2*actor->radius>>FRACBITS; - fixed_t hei = actor->height>>FRACBITS; - mobj_t *particle = P_SpawnMobjFromMobj(actor, - P_RandomRange(rad, -rad)<radius>>FRACBITS; + hei = actor->height>>FRACBITS; + particle = P_SpawnMobjFromMobj(actor, + P_RandomRange(rad, -rad)<tracer, special); - if (special->target && (special->target->type == MT_SPINMACEPOINT || special->target->type == MT_HIDDEN_SLING)) + if (special->tracer && !(special->tracer->flags2 & MF2_STRONGBOX)) { player->powers[pw_carry] = CR_MACESPIN; S_StartSound(toucher, sfx_spin); @@ -1485,6 +1485,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Can't jump first frame player->pflags |= PF_JUMPSTASIS; + return; case MT_BIGMINE: case MT_BIGAIRMINE: diff --git a/src/p_mobj.c b/src/p_mobj.c index 3ff5bfab5..57df82578 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6453,6 +6453,132 @@ static void P_NightsItemChase(mobj_t *thing) P_Attract(thing, thing->tracer, true); } +// +// P_MaceRotate +// Spins an object around its target, or, swings it from side to side. +// +static void P_MaceRotate(mobj_t *mobj) +{ + TVector v; + TVector *res; + fixed_t radius, dist; + angle_t fa; + INT32 prevswing; + boolean donetwice = false; + + // Tracer was removed. + if (!mobj->health) + return; + else if (!mobj->tracer) + { + P_KillMobj(mobj, NULL, NULL, 0); + return; + } + + mobj->momx = mobj->momy = mobj->momz = 0; + + prevswing = mobj->threshold; + mobj->threshold += mobj->tracer->lastlook; + mobj->threshold &= FINEMASK; + + dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed); + + // Radius of the link's rotation. + radius = FixedMul(dist * mobj->movecount, mobj->tracer->scale) + mobj->tracer->extravalue1; + +maceretry: + + // Set the top speed for the link if it happens to be over that speed. + if (mobj->tracer->lastlook > mobj->tracer->friction) + mobj->tracer->lastlook = mobj->tracer->friction; + + fa = (FixedAngle(mobj->tracer->movefactor*FRACUNIT) >> ANGLETOFINESHIFT); + radius = FixedMul(FINECOSINE(fa), radius); + v[1] = -FixedMul(FINESINE(fa), radius) + + FixedMul(dist * mobj->movefactor, mobj->tracer->scale); + v[3] = FRACUNIT; + + // Swinging Chain. + if (mobj->tracer->flags2 & MF2_STRONGBOX) + { + fixed_t swingmagnitude = FixedMul(FINECOSINE(mobj->threshold), mobj->tracer->lastlook << FRACBITS); + prevswing = FINECOSINE(prevswing); + + if (!donetwice + && (mobj->flags2 & MF2_BOSSNOTRAP) // at the end of the chain and can play a sound + && ((prevswing > 0) != (swingmagnitude > 0))) // just passed its lowest point + S_StartSound(mobj, mobj->info->activesound); + + fa = ((FixedAngle(swingmagnitude) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK; + + v[0] = FixedMul(FINESINE(fa), -radius); + v[2] = FixedMul(FINECOSINE(fa), -radius); + } + // Rotating Chain. + else + { + prevswing = (prevswing + mobj->friction) & FINEMASK; + fa = (mobj->threshold + mobj->friction) & FINEMASK; + + if (!donetwice + && (mobj->flags2 & MF2_BOSSNOTRAP) // at the end of the chain and can play a sound + && (!(prevswing > (FINEMASK/2)) && (fa > (FINEMASK/2)))) // completed a full swing + S_StartSound(mobj, mobj->info->activesound); + + v[0] = FixedMul(FINECOSINE(fa), radius); + v[2] = FixedMul(FINESINE(fa), radius); + } + + // Calculate the angle matrixes for the link. + res = VectorMatrixMultiply(v, *RotateXMatrix(mobj->tracer->threshold << ANGLETOFINESHIFT)); + M_Memcpy(&v, res, sizeof(v)); + res = VectorMatrixMultiply(v, *RotateZMatrix(mobj->tracer->health << ANGLETOFINESHIFT)); + M_Memcpy(&v, res, sizeof(v)); + + // Cut the height to align the link with the axis. + if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN) + v[2] -= P_MobjFlip(mobj)*mobj->height/4; + else + v[2] -= P_MobjFlip(mobj)*mobj->height/2; + + P_UnsetThingPosition(mobj); + + // Add on the appropriate distances to the center's co-ordinates. + mobj->x = mobj->tracer->x + v[0]; + mobj->y = mobj->tracer->y + v[1]; + mobj->z = mobj->tracer->z + v[2]; + + P_SetThingPosition(mobj); + + if (donetwice) + return; + + if (mobj->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) + return; + + if ((fa = ((mobj->tracer->threshold & (FINEMASK/2)) << ANGLETOFINESHIFT)) > ANGLE_45 && fa < ANGLE_135) // only move towards center when the motion is towards/away from the ground, rather than alongside it + return; + + if (mobj->subsector->sector->ffloors) + P_AdjustMobjFloorZ_FFloors(mobj, mobj->subsector->sector, 2); + + // Variable reuse + if (mobj->floorz > mobj->z) + dist = (mobj->floorz - mobj->tracer->z); + else if (mobj->ceilingz < mobj->z) + dist = (mobj->ceilingz - mobj->tracer->z); + else + return; + + if ((dist = FixedDiv(dist, v[2])) > FRACUNIT) + return; + + radius = FixedMul(radius, dist); + donetwice = true; + dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed); + goto maceretry; +} + static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) { if (!thing->target || thing->target->health <= 0 || !thing->target->player @@ -6810,6 +6936,13 @@ void P_MobjThinker(mobj_t *mobj) // fade out when nearing the end of fuse... mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << FF_TRANSSHIFT); + if (mobj->flags2 & MF2_MACEROTATE) + { + P_MaceRotate(mobj); + if (P_MobjWasRemoved(mobj)) + return; + } + // Special thinker for scenery objects if (mobj->flags & MF_SCENERY) { @@ -7456,7 +7589,7 @@ void P_MobjThinker(mobj_t *mobj) } } break; - case MT_SPINMACEPOINT: + case MT_FIREBARPOINT: if (leveltime & 1) { if (mobj->lastlook > mobj->movecount) @@ -9771,16 +9904,20 @@ void P_SpawnMapThing(mapthing_t *mthing) mobj->movedir = mthing->extrainfo; break; case MT_MACEPOINT: - case MT_SWINGMACEPOINT: - case MT_HANGMACEPOINT: - case MT_SPINMACEPOINT: + case MT_CHAINMACEPOINT: + case MT_SPRINGBALLPOINT: + case MT_CHAINPOINT: + case MT_FIREBARPOINT: + case MT_CUSTOMMACEPOINT: { - fixed_t mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed, thresholdset, radiusfactor = 1; - mobjtype_t chainlink = MT_SMALLMACECHAIN; - mobjtype_t macetype = MT_SMALLMACE; - mobjtype_t firsttype; - const boolean hazard = (mobj->type == MT_MACEPOINT || mobj->type == MT_SWINGMACEPOINT); + fixed_t mlength, mlengthset, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mnumspokesset, mpinch, mroll, mnumnospokes, mwidth, mmin, msound, radiusfactor; + angle_t mspokeangle; + mobjtype_t chainlink, macetype, firsttype, linktype; + boolean mdoall = true; mobj_t *spawnee; + mobjflag_t mflagsapply; + mobjflag2_t mflags2apply; + mobjeflag_t meflagsapply; INT32 line; const size_t mthingi = (size_t)(mthing - mapthings); @@ -9794,91 +9931,239 @@ void P_SpawnMapThing(mapthing_t *mthing) return; } /* -No deaf - small -Deaf - big +mapthing - +MTF_AMBUSH : + MT_SPRINGBALLPOINT - upgrade from yellow to red spring + anything else - bigger mace/chain theory +MTF_OBJECTSPECIAL - force silent +MTF_GRAVFLIP - flips objects, doesn't affect chain arrangements +Parameter value : number of "spokes" +linedef - ML_NOCLIMB : -SPINMACEPOINT - Direction not controllable -MACEPOINT, SWINGMACEPOINT - Chain links are replaced with maces + MT_CHAINPOINT/MT_CHAINMACEPOINT with ML_EFFECT1 applied - Direction not controllable + anything else - no functionality +ML_EFFECT1 : Swings instead of spins +ML_EFFECT2 : Linktype is replaced with macetype for all spokes not ending in chains (inverted for MT_FIREBARPOINT) +ML_EFFECT3 : Spawn a bonus macetype at the hinge point +ML_EFFECT4 : Don't clip inside the ground */ mlength = abs(lines[line].dx >> FRACBITS); - mspeed = abs(lines[line].dy >> FRACBITS); - mxspeed = sides[lines[line].sidenum[0]].textureoffset >> FRACBITS; - mzspeed = sides[lines[line].sidenum[0]].rowoffset >> FRACBITS; - mstartangle = lines[line].frontsector->floorheight >> FRACBITS; - mmaxspeed = lines[line].frontsector->ceilingheight >> FRACBITS; + mspeed = abs(lines[line].dy >> (FRACBITS - 4)); + mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360; + if ((mmaxspeed = sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) < mspeed) + mmaxspeed = mspeed << 1; + mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360; + myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360; - mstartangle %= 360; - mxspeed %= 360; - mzspeed %= 360; + mnumspokes = mthing->extrainfo + 1; + mspokeangle = FixedAngle((360*FRACUNIT)/mnumspokes)>>ANGLETOFINESHIFT; + + if (lines[line].backsector) + { + mpinch = (lines[line].backsector->floorheight >> FRACBITS) % 360; + mroll = (lines[line].backsector->ceilingheight >> FRACBITS) % 360; + mnumnospokes = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS); + if ((mwidth = sides[lines[line].sidenum[1]].rowoffset >> FRACBITS) < 0) + mwidth = 0; + } + else + mpinch = mroll = mnumnospokes = mwidth = 0; CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n" "Length is %d\n" "Speed is %d\n" "Phase is %d\n" - "Angle is %d\n" - "Tilt is %d\n" - "Max. speed is %d\n", - sizeu1(mthingi), mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed); + "Yaw is %d\n" + "Pitch is %d\n" + "Max. speed is %d\n" + "No. of spokes is %d\n" + "Pinch is %d\n" + "Roll is %d\n" + "No. of antispokes is %d\n" + "Width is %d\n", + sizeu1(mthingi), mlength, mspeed, mphase, myaw, mpitch, mmaxspeed, mnumspokes, mpinch, mroll, mnumnospokes, mwidth); - mobj->lastlook = mspeed << 4; + if (mnumnospokes > 0 && (mnumnospokes < mnumspokes)) + mnumnospokes = mnumspokes/mnumnospokes; + else + mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes - 1) : 0); + + mobj->lastlook = mspeed; mobj->movecount = mobj->lastlook; - mobj->health = (FixedAngle(mzspeed*FRACUNIT)>>ANGLETOFINESHIFT); - mobj->threshold = (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT); - mobj->movefactor = mobj->threshold; + mobj->health = (FixedAngle(myaw*FRACUNIT)>>ANGLETOFINESHIFT); + mobj->threshold = (FixedAngle(mpitch*FRACUNIT)>>ANGLETOFINESHIFT); mobj->friction = mmaxspeed; + mobj->movefactor = mpinch; - if (mthing->options & MTF_AMBUSH) + // Mobjtype selection + switch(mobj->type) { - chainlink = MT_BIGMACECHAIN; - macetype = MT_BIGMACE; + case MT_SPRINGBALLPOINT: + macetype = ((mthing->options & MTF_AMBUSH) + ? MT_REDSPRINGBALL + : MT_YELLOWSPRINGBALL); + chainlink = MT_SMALLMACECHAIN; + break; + case MT_FIREBARPOINT: + macetype = ((mthing->options & MTF_AMBUSH) + ? MT_BIGFIREBAR + : MT_SMALLFIREBAR); + chainlink = MT_NULL; + break; + case MT_CUSTOMMACEPOINT: + macetype = (mobjtype_t)sides[lines[line].sidenum[0]].toptexture; + if (lines[line].backsector) + chainlink = (mobjtype_t)sides[lines[line].sidenum[1]].toptexture; + else + chainlink = MT_NULL; + break; + default: + if (mthing->options & MTF_AMBUSH) + { + macetype = MT_BIGMACE; + chainlink = MT_BIGMACECHAIN; + } + else + { + macetype = MT_SMALLMACE; + chainlink = MT_SMALLMACECHAIN; + } + break; } - if (lines[line].flags & ML_NOCLIMB) - { - if (hazard) - { - chainlink = macetype; - radiusfactor = 2; // Double the radius. - } - else - mobj->flags |= MF_SLIDEME; - } + if (!macetype) + break; - mobj->reactiontime = 0; - - if (!mspeed || mthing->options & MTF_OBJECTSPECIAL) - mobj->flags2 |= MF2_BOSSNOTRAP; // shut up maces. - - thresholdset = FixedAngle(mxspeed*FRACUNIT)>>ANGLETOFINESHIFT; - - if (hazard) // outermost mace + if (mobj->type != MT_CHAINPOINT) { firsttype = macetype; mlength++; } else + { + if (!mlength) + break; firsttype = chainlink; - - if (mlength) // outermost mace/link - { - spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, firsttype); - P_SetTarget(&spawnee->target, mobj); - - spawnee->threshold = thresholdset; - spawnee->reactiontime = radiusfactor*(mlength--); - - spawnee->flags2 |= MF2_AMBUSH; } - while (mlength > 0) - { - spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, chainlink); - P_SetTarget(&spawnee->target, mobj); + // Adjustable direction + if (lines[line].flags & ML_NOCLIMB) + mobj->flags |= MF_SLIDEME; - spawnee->threshold = thresholdset; - spawnee->reactiontime = radiusfactor*(mlength--); + // Swinging + if (lines[line].flags & ML_EFFECT1) + { + mobj->flags2 |= MF2_STRONGBOX; + mmin = ((mnumnospokes > 1) ? 1 : 0); } + else + mmin = mnumspokes; + + // Make the links the same type as the end - repeated below + if ((mobj->type != MT_CHAINPOINT) && (!(lines[line].flags & ML_EFFECT2) == (mobj->type == MT_FIREBARPOINT))) // exclusive or + { + linktype = macetype; + radiusfactor = 2; // Double the radius. + } + else + radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); + + mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP|MF_NOCLIPHEIGHT)); + mflags2apply = (MF2_MACEROTATE|((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0)); + meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0); + + msound = ((firsttype == chainlink) ? 0 : (mwidth & 1)); + + // Quick and easy preparatory variable setting + mphase = (FixedAngle(mphase*FRACUNIT)>>ANGLETOFINESHIFT); + mroll = (FixedAngle(mroll*FRACUNIT)>>ANGLETOFINESHIFT); + +#define makemace(mobjtype, dist, moreflags2) P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\ + P_SetTarget(&spawnee->tracer, mobj);\ + spawnee->threshold = mphase;\ + spawnee->friction = mroll;\ + spawnee->movefactor = mwidth;\ + spawnee->movecount = dist;\ + spawnee->angle = myaw;\ + spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\ + spawnee->flags2 |= (mflags2apply|moreflags2);\ + spawnee->eflags |= meflagsapply + +domaceagain: + mnumspokesset = mnumspokes; + + if (mdoall && lines[line].flags & ML_EFFECT3) // Innermost mace/link + { spawnee = makemace(macetype, 0, MF2_AMBUSH); } + + // The actual spawning of spokes + while (mnumspokesset-- > 0) + { + // Offsets + if (lines[line].flags & ML_EFFECT1) // Swinging + mroll = (mroll - mspokeangle) & FINEMASK; + else // Spinning + mphase = (mphase - mspokeangle) & FINEMASK; + + if (mnumnospokes && !(mnumspokesset % mnumnospokes)) // Skipping a "missing" spoke + { + if (mobj->type != MT_CHAINMACEPOINT) + continue; + + firsttype = linktype = chainlink; + mlengthset = 1 + (mlength - 1)*radiusfactor; + radiusfactor = 1; + } + else + { + if (mobj->type == MT_CHAINMACEPOINT) + { + // Make the links the same type as the end - repeated above + if (lines[line].flags & ML_EFFECT2) + { + linktype = macetype; + radiusfactor = 2; + } + else + { + linktype = chainlink; + radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); + } + + firsttype = macetype; + } + + mlengthset = mlength; + } + + // Outermost mace/link + spawnee = makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH); + + if (mspeed && (mwidth == msound) && !(mthing->options & MTF_OBJECTSPECIAL) && mnumspokesset <= mmin) // Can it make a sound? + spawnee->flags2 |= MF2_BOSSNOTRAP; + + if (!mdoall || !linktype) + continue; + + // The rest of the links + while (mlengthset > 0) + { spawnee = makemace(linktype, radiusfactor*(mlengthset--), 0); } + } + + if (mwidth > 0) + { + mwidth *= -1; + goto domaceagain; + } + else if (mwidth != 0) + { + if ((mwidth = -(mwidth + ((firsttype == chainlink) ? 1 : 2))) < 0) + break; + mdoall = false; + goto domaceagain; + } + +#undef makemace break; } @@ -11235,4 +11520,4 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo newmobj->destscale = mobj->destscale; P_SetScale(newmobj, mobj->scale); return newmobj; -} +} \ No newline at end of file diff --git a/src/p_mobj.h b/src/p_mobj.h index f6ebd3cad..c6e1bfbf2 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -194,6 +194,7 @@ typedef enum MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) + MF2_MACEROTATE = 1<<30, // Thinker calls P_MaceRotate around tracer // free: to and including 1<<31 } mobjflag2_t; diff --git a/src/p_setup.c b/src/p_setup.c index 4f11c10d0..457c8313f 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1578,6 +1578,7 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum) break; } + case 9: // Mace parameters case 14: // Bustable block parameters case 15: // Fan particle spawner parameters case 425: // Calls P_SetMobjState on calling mobj diff --git a/src/p_user.c b/src/p_user.c index 36b8eddf7..707e2e302 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9969,7 +9969,7 @@ void P_PlayerAfterThink(player_t *player) } } } - else if (player->powers[pw_carry] == CR_MACESPIN && player->mo->tracer && player->mo->tracer->target) + else if (player->powers[pw_carry] == CR_MACESPIN && player->mo->tracer && player->mo->tracer->tracer) { player->mo->height = P_GetPlayerSpinHeight(player); // tracer is what you're hanging onto.... @@ -9985,14 +9985,14 @@ void P_PlayerAfterThink(player_t *player) player->pflags &= ~PF_THOKKED; if (cmd->forwardmove > 0) - player->mo->tracer->target->lastlook += 2; - else if (cmd->forwardmove < 0 && player->mo->tracer->target->lastlook > player->mo->tracer->target->movecount) - player->mo->tracer->target->lastlook -= 2; + player->mo->tracer->tracer->lastlook += 2; + else if (cmd->forwardmove < 0 && player->mo->tracer->tracer->lastlook > player->mo->tracer->tracer->movecount) + player->mo->tracer->tracer->lastlook -= 2; - if ((player->mo->tracer->target->flags & MF_SLIDEME) // Noclimb on chain parameters gives this + if ((player->mo->tracer->tracer->flags & MF_SLIDEME) // Noclimb on chain parameters gives this && !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode? { - player->mo->tracer->target->health += cmd->sidemove; + player->mo->tracer->tracer->health += cmd->sidemove; player->mo->angle += cmd->sidemove< ANGLE_MAX if (!demoplayback || P_AnalogMove(player)) From 25fb318a0b1f128cb6ae9ffac4f3857fd9dc7355 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 4 Jul 2017 14:58:58 +0100 Subject: [PATCH 5/8] * Fixed a typo with the bit-shifting of the max speed, meaning that it wasn't being set as desired. * Made the speed capping/minimising done at the point of changing it via player control, as opposed to the point of macerotate, in an attempt to fix a potential cause of mace rotation desynchronisation (not netplay, just https://cdn.discordapp.com/attachments/293238104096112641/331453363499696139/srb20180.gif stuff.) --- src/p_mobj.c | 6 +----- src/p_user.c | 12 +++++++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 57df82578..f95d5a0a5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6488,10 +6488,6 @@ static void P_MaceRotate(mobj_t *mobj) maceretry: - // Set the top speed for the link if it happens to be over that speed. - if (mobj->tracer->lastlook > mobj->tracer->friction) - mobj->tracer->lastlook = mobj->tracer->friction; - fa = (FixedAngle(mobj->tracer->movefactor*FRACUNIT) >> ANGLETOFINESHIFT); radius = FixedMul(FINECOSINE(fa), radius); v[1] = -FixedMul(FINESINE(fa), radius) @@ -9951,7 +9947,7 @@ ML_EFFECT4 : Don't clip inside the ground mlength = abs(lines[line].dx >> FRACBITS); mspeed = abs(lines[line].dy >> (FRACBITS - 4)); mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360; - if ((mmaxspeed = sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) < mspeed) + if ((mmaxspeed = sides[lines[line].sidenum[0]].rowoffset >> (FRACBITS - 4)) < mspeed) mmaxspeed = mspeed << 1; mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360; myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360; diff --git a/src/p_user.c b/src/p_user.c index 707e2e302..519bffa3f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -9985,9 +9985,15 @@ void P_PlayerAfterThink(player_t *player) player->pflags &= ~PF_THOKKED; if (cmd->forwardmove > 0) - player->mo->tracer->tracer->lastlook += 2; - else if (cmd->forwardmove < 0 && player->mo->tracer->tracer->lastlook > player->mo->tracer->tracer->movecount) - player->mo->tracer->tracer->lastlook -= 2; + { + if ((player->mo->tracer->tracer->lastlook += 2) > player->mo->tracer->tracer->friction) + player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->friction; + } + else if (cmd->forwardmove < 0) + { + if ((player->mo->tracer->tracer->lastlook -= 2) < player->mo->tracer->tracer->movecount) + player->mo->tracer->tracer->lastlook = player->mo->tracer->tracer->movecount; + } if ((player->mo->tracer->tracer->flags & MF_SLIDEME) // Noclimb on chain parameters gives this && !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode? From fe756d567e2a18fc3930c7c690b866a32a309943 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Wed, 12 Jul 2017 14:01:16 +0100 Subject: [PATCH 6/8] Add a "bias" to collision with chain ferris wheels to make it more likely that you'll grab one nearer to the center if you could potentially hit two in the next frame (previously was blockmap order dependent, which was never consistent) --- src/p_inter.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/p_inter.c b/src/p_inter.c index 99289165b..972d19216 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1471,6 +1471,15 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->powers[pw_flashing]) return; + if (special->movefactor && special->tracer && (angle_t)special->tracer->health != ANGLE_90 && (angle_t)special->tracer->health != ANGLE_270) + { // I don't expect you to understand this, Mr Bond... + angle_t ang = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->tracer->threshold; + if ((special->movefactor > 0) == ((angle_t)special->tracer->health > ANGLE_90 && (angle_t)special->tracer->health < ANGLE_270)) + ang += ANGLE_180; + if (ang < ANGLE_180) + return; // I expect you to die. + } + P_ResetPlayer(player); P_SetTarget(&toucher->tracer, special); From d135f6446440cad249616f3b9578e8c700e87900 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 7 Aug 2017 18:58:41 +0100 Subject: [PATCH 7/8] Crash prevention --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f95d5a0a5..60f569e5a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6546,7 +6546,7 @@ maceretry: P_SetThingPosition(mobj); - if (donetwice) + if (donetwice || P_MobjWasRemoved(mobj)) return; if (mobj->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) From 2e1b81b5daab23de7ba8c6db91f93b35874204e2 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 7 Aug 2017 19:23:48 +0100 Subject: [PATCH 8/8] Woops, silly find and replace --- src/p_mobj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 60f569e5a..42a3a4429 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7585,7 +7585,8 @@ void P_MobjThinker(mobj_t *mobj) } } break; - case MT_FIREBARPOINT: + case MT_CHAINPOINT: + case MT_CHAINMACEPOINT: if (leveltime & 1) { if (mobj->lastlook > mobj->movecount)