diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ae7a8fbba..6d52cb697 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,7 +1,18 @@ +October 26, 2006 +- Removed A_JumpSet and merged its functionality with A_Jump by turning + A_Jump into a varargs function. +- Fixed: P_MorphPlayer() should check that the desired type is actually a + PlayerPawn. +- Added an optional parameter to the morphme ccmd that specifies the player + class to morph into. +- Changed the SetActorPitch, SetActorAngle, Thing_Spawn*, Thing_Projectile*, + and Thing_Move functions so that TID 0 affects the activator. + October 25, 2006 (Changes by Graf Zahl) - Moved the sector type translation for Doom format maps into a simple lump in zdoom.pk3. -- Changed Line_SetIdentification so that the fifth arg is a high-byte for the line ID. +- Changed Line_SetIdentification so that the fifth arg is a high-byte for the + line ID. October 23, 2006 - Added the A_JumpSet function for what seems to be a fairly common scenario. diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index e80ee975b..cd02d8b6a 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -175,8 +175,16 @@ CCMD (morphme) if (CheckCheatmode ()) return; - Net_WriteByte (DEM_GENERICCHEAT); - Net_WriteByte (CHT_MORPH); + if (argv.argc() == 1) + { + Net_WriteByte (DEM_GENERICCHEAT); + Net_WriteByte (CHT_MORPH); + } + else + { + Net_WriteByte (DEM_MORPHEX); + Net_WriteString (argv[1]); + } } CCMD (anubis) diff --git a/src/d_net.cpp b/src/d_net.cpp index 96caa1941..b1294ff75 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2291,6 +2291,16 @@ void Net_DoCommand (int type, BYTE **stream, int player) } break; + case DEM_MORPHEX: + { + s = ReadString (stream); + const char *msg = cht_Morph (players + player, PClass::FindClass (s), false); + if (player == consoleplayer) + { + Printf ("%s\n", *msg != '\0' ? msg : "Morph failed."); + } + } + break; default: I_Error ("Unknown net command: %d", type); @@ -2325,6 +2335,7 @@ void Net_SkipCommand (int type, BYTE **stream) case DEM_SUMMON: case DEM_SUMMONFRIEND: case DEM_SPRAY: + case DEM_MORPHEX: skip = strlen ((char *)(*stream)) + 1; break; diff --git a/src/d_protocol.h b/src/d_protocol.h index e7642b814..8b739fc34 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -142,6 +142,7 @@ enum EDemoCommand DEM_RUNSCRIPT2, // 40 Same as DEM_RUNSCRIPT, but always executes DEM_CHECKAUTOSAVE, // 41 Check if the user has autosaves enabled. Ignored for demoplayback. DEM_DOAUTOSAVE, // 42 An autosave should be made + DEM_MORPHEX, // 43 String: The class to morph to. }; // The following are implemented by cht_DoCheat in m_cheat.cpp diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 86386f711..ae38333df 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -48,11 +48,14 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype) { // Dead players cannot morph return false; } - if (spawntype == NULL) { return false; } + if (!spawntype->IsDescendantOf (RUNTIME_CLASS(APlayerPawn))) + { + return false; + } morphed = static_cast(Spawn (spawntype, actor->x, actor->y, actor->z, NO_REPLACE)); DObject::PointerSubstitution (actor, morphed); diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index f2a9feca9..f5ffc2aba 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -122,18 +122,7 @@ void cht_DoCheat (player_t *player, int cheat) break; case CHT_MORPH: - if (player->morphTics) - { - if (P_UndoPlayerMorph (player)) - { - msg = "You feel like yourself again"; - } - } - else if (P_MorphPlayer (player, - PClass::FindClass (gameinfo.gametype == GAME_Heretic ? NAME_ChickenPlayer : NAME_PigPlayer))) - { - msg = "You feel strange..."; - } + msg = cht_Morph (player, PClass::FindClass (gameinfo.gametype == GAME_Heretic ? NAME_ChickenPlayer : NAME_PigPlayer), true); break; case CHT_NOTARGET: @@ -415,6 +404,31 @@ void cht_DoCheat (player_t *player, int cheat) Printf ("%s is a cheater: %s\n", player->userinfo.netname, msg); } +const char *cht_Morph (player_t *player, const PClass *morphclass, bool quickundo) +{ + if (player->mo == NULL) + { + return ""; + } + PClass *oldclass = player->mo->GetClass(); + if (player->morphTics) + { + if (P_UndoPlayerMorph (player)) + { + if (!quickundo && oldclass != morphclass && P_MorphPlayer (player, morphclass)) + { + return "You feel even stranger."; + } + return "You feel like yourself again."; + } + } + else if (P_MorphPlayer (player, morphclass)) + { + return "You feel strange..."; + } + return ""; +} + void GiveSpawner (player_t *player, const PClass *type, int amount) { if (player->mo == NULL || player->health <= 0) diff --git a/src/m_cheat.h b/src/m_cheat.h index 21146fe9a..86b9d5e70 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -29,8 +29,10 @@ // [RH] Functions that actually perform the cheating class player_s; +struct PClass; void cht_DoCheat (player_s *player, int cheat); void cht_Give (player_s *player, char *item, int amount=1); void cht_Suicide (player_s *player); +const char *cht_Morph (player_s *player, const PClass *morphclass, bool quickundo); #endif diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 92a7dacb0..c4ecf98af 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4793,14 +4793,14 @@ int DLevelScript::RunScript () // Like Thing_Projectile(Gravity) specials, but you can give the // projectile a TID. // Thing_Projectile2 (tid, type, angle, speed, vspeed, gravity, newtid); - P_Thing_Projectile (STACK(7), STACK(6), NULL, ((angle_t)(STACK(5)<<24)), + P_Thing_Projectile (STACK(7), activator, STACK(6), NULL, ((angle_t)(STACK(5)<<24)), STACK(4)<<(FRACBITS-3), STACK(3)<<(FRACBITS-3), 0, NULL, STACK(2), STACK(1), false); sp -= 7; break; case PCD_SPAWNPROJECTILE: // Same, but takes an actor name instead of a spawn ID. - P_Thing_Projectile (STACK(7), 0, FBehavior::StaticLookupString (STACK(6)), ((angle_t)(STACK(5)<<24)), + P_Thing_Projectile (STACK(7), activator, 0, FBehavior::StaticLookupString (STACK(6)), ((angle_t)(STACK(5)<<24)), STACK(4)<<(FRACBITS-3), STACK(3)<<(FRACBITS-3), 0, NULL, STACK(2), STACK(1), false); sp -= 7; break; @@ -4903,6 +4903,11 @@ int DLevelScript::RunScript () break; case PCD_SETACTORANGLE: // [GRB] + if (STACK(2) == 0) + { + activator->angle = STACK(1) << 16; + } + else { FActorIterator iterator (STACK(2)); AActor *actor; @@ -4916,6 +4921,11 @@ int DLevelScript::RunScript () break; case PCD_SETACTORPITCH: + if (STACK(2) == 0) + { + activator->angle = STACK(1) << 16; + } + else { FActorIterator iterator (STACK(2)); AActor *actor; diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 49c3a0f23..886285a73 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1138,14 +1138,14 @@ FUNC(LS_Thing_Damage) FUNC(LS_Thing_Projectile) // Thing_Projectile (tid, type, angle, speed, vspeed) { - return P_Thing_Projectile (arg0, arg1, NULL, BYTEANGLE(arg2), arg3<<(FRACBITS-3), + return P_Thing_Projectile (arg0, it, arg1, NULL, BYTEANGLE(arg2), arg3<<(FRACBITS-3), arg4<<(FRACBITS-3), 0, NULL, 0, 0, false); } FUNC(LS_Thing_ProjectileGravity) // Thing_ProjectileGravity (tid, type, angle, speed, vspeed) { - return P_Thing_Projectile (arg0, arg1, NULL, BYTEANGLE(arg2), arg3<<(FRACBITS-3), + return P_Thing_Projectile (arg0, it, arg1, NULL, BYTEANGLE(arg2), arg3<<(FRACBITS-3), arg4<<(FRACBITS-3), 0, NULL, 1, 0, false); } @@ -1315,35 +1315,35 @@ FUNC(LS_Thing_Hate) FUNC(LS_Thing_ProjectileAimed) // Thing_ProjectileAimed (tid, type, speed, target, newtid) { - return P_Thing_Projectile (arg0, arg1, NULL, 0, arg2<<(FRACBITS-3), 0, arg3, it, 0, arg4, false); + return P_Thing_Projectile (arg0, it, arg1, NULL, 0, arg2<<(FRACBITS-3), 0, arg3, it, 0, arg4, false); } FUNC(LS_Thing_ProjectileIntercept) // Thing_ProjectileIntercept (tid, type, speed, target, newtid) { - return P_Thing_Projectile (arg0, arg1, NULL, 0, arg2<<(FRACBITS-3), 0, arg3, it, 0, arg4, true); + return P_Thing_Projectile (arg0, it, arg1, NULL, 0, arg2<<(FRACBITS-3), 0, arg3, it, 0, arg4, true); } // [BC] added newtid for next two FUNC(LS_Thing_Spawn) // Thing_Spawn (tid, type, angle, newtid) { - return P_Thing_Spawn (arg0, arg1, BYTEANGLE(arg2), true, arg3); + return P_Thing_Spawn (arg0, it, arg1, BYTEANGLE(arg2), true, arg3); } FUNC(LS_Thing_SpawnNoFog) // Thing_SpawnNoFog (tid, type, angle, newtid) { - return P_Thing_Spawn (arg0, arg1, BYTEANGLE(arg2), false, arg3); + return P_Thing_Spawn (arg0, it, arg1, BYTEANGLE(arg2), false, arg3); } FUNC(LS_Thing_SpawnFacing) // Thing_SpawnFacing (tid, type, nofog, newtid) { - return P_Thing_Spawn (arg0, arg1, ANGLE_MAX, arg2 ? false : true, arg3); + return P_Thing_Spawn (arg0, it, arg1, ANGLE_MAX, arg2 ? false : true, arg3); } -static bool DoThingRaise(AActor * thing) +static bool DoThingRaise(AActor *thing) { if (thing == NULL) return false; // not valid @@ -1448,7 +1448,7 @@ FUNC(LS_Thing_SetGoal) FUNC(LS_Thing_Move) // [BC] // Thing_Move (tid, mapspot, nofog) { - return P_Thing_Move (arg0, arg1, arg2 ? false : true); + return P_Thing_Move (arg0, it, arg1, arg2 ? false : true); } FUNC(LS_Thing_SetTranslation) diff --git a/src/p_local.h b/src/p_local.h index a4ad893b4..13fb681dc 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -125,12 +125,12 @@ void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz); #define MAX_SPAWNABLES (256) extern const PClass *SpawnableThings[MAX_SPAWNABLES]; -bool P_Thing_Spawn (int tid, int type, angle_t angle, bool fog, int newtid); -bool P_Thing_Projectile (int tid, int type, const char * type_name, angle_t angle, +bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog, int newtid); +bool P_Thing_Projectile (int tid, AActor *source, int type, const char * type_name, angle_t angle, fixed_t speed, fixed_t vspeed, int dest, AActor *forcedest, int gravity, int newtid, bool leadTarget); -bool P_MoveThing(AActor * source, fixed_t x, fixed_t y, fixed_t z, bool fog); -bool P_Thing_Move (int tid, int mapspot, bool fog); +bool P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog); +bool P_Thing_Move (int tid, AActor *source, int mapspot, bool fog); // // P_ENEMY diff --git a/src/p_things.cpp b/src/p_things.cpp index 927e80b4a..0a89c9620 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -51,7 +51,7 @@ const PClass *SpawnableThings[MAX_SPAWNABLES]; static FRandom pr_leadtarget ("LeadTarget"); -bool P_Thing_Spawn (int tid, int type, angle_t angle, bool fog, int newtid) +bool P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog, int newtid) { int rtn = 0; const PClass *kind; @@ -70,7 +70,15 @@ bool P_Thing_Spawn (int tid, int type, angle_t angle, bool fog, int newtid) if ((GetDefaultByType (kind)->flags3 & MF3_ISMONSTER) && (dmflags & DF_NO_MONSTERS)) return false; - while ( (spot = iterator.Next ()) ) + if (tid == 0) + { + spot = source; + } + else + { + spot = iterator.Next(); + } + while (spot != NULL) { mobj = Spawn (kind, spot->x, spot->y, spot->z, ALLOW_REPLACE); @@ -109,6 +117,7 @@ bool P_Thing_Spawn (int tid, int type, angle_t angle, bool fog, int newtid) rtn = false; } } + spot = iterator.Next(); } return rtn != 0; @@ -117,7 +126,7 @@ bool P_Thing_Spawn (int tid, int type, angle_t angle, bool fog, int newtid) // [BC] Added // [RH] Fixed -bool P_MoveThing(AActor * source, fixed_t x, fixed_t y, fixed_t z, bool fog) +bool P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog) { fixed_t oldx, oldy, oldz; @@ -142,13 +151,16 @@ bool P_MoveThing(AActor * source, fixed_t x, fixed_t y, fixed_t z, bool fog) } } -bool P_Thing_Move (int tid, int mapspot, bool fog) +bool P_Thing_Move (int tid, AActor *source, int mapspot, bool fog) { - FActorIterator iterator1 (tid); - FActorIterator iterator2 (mapspot); - AActor *source, *target; + AActor *target; - source = iterator1.Next (); + if (tid != 0) + { + FActorIterator iterator1(tid); + source = iterator1.Next(); + } + FActorIterator iterator2 (mapspot); target = iterator2.Next (); if (source != NULL && target != NULL) @@ -158,7 +170,7 @@ bool P_Thing_Move (int tid, int mapspot, bool fog) return false; } -bool P_Thing_Projectile (int tid, int type, const char * type_name, angle_t angle, +bool P_Thing_Projectile (int tid, AActor *source, int type, const char * type_name, angle_t angle, fixed_t speed, fixed_t vspeed, int dest, AActor *forcedest, int gravity, int newtid, bool leadTarget) { @@ -191,7 +203,15 @@ bool P_Thing_Projectile (int tid, int type, const char * type_name, angle_t angl if ((defflags3 & MF3_ISMONSTER) && (dmflags & DF_NO_MONSTERS)) return false; - while ( (spot = iterator.Next ()) ) + if (tid == 0) + { + spot = source; + } + else + { + spot = iterator.Next(); + } + while (spot != NULL) { FActorIterator tit (dest); @@ -375,7 +395,8 @@ nolead: } } } while (dest != 0 && (targ = tit.Next())); - } + } + spot = iterator.Next(); } return rtn != 0; diff --git a/src/thingdef.cpp b/src/thingdef.cpp index e8955483c..c98205f56 100644 --- a/src/thingdef.cpp +++ b/src/thingdef.cpp @@ -457,7 +457,6 @@ ACTOR(PlaySoundEx) ACTOR(StopSoundEx) ACTOR(SeekerMissile) ACTOR(Jump) -ACTOR(JumpSet) ACTOR(ExplodeParms) ACTOR(CallSpecial) ACTOR(CustomMissile) @@ -527,6 +526,9 @@ ACTOR(Stop) * c = color * x = expression * y = expression + * If the final character is a +, the previous parameter is repeated indefinitely, + * and an "imaginary" first parameter is inserted containing the total number of + * parameters passed. */ #define FUNC(name, parm) { #name, name, parm }, // Declare the code pointer table @@ -677,8 +679,7 @@ AFuncDesc AFTable[]= FUNC(A_PlaySoundEx, "STi" ) FUNC(A_StopSoundEx, "T" ) FUNC(A_SeekerMissile, "XX" ) - FUNC(A_Jump, "XL" ) - FUNC(A_JumpSet, "XLLllllllllllllllllll") + FUNC(A_Jump, "XL+" ) FUNC(A_CustomMissile, "MXXxxx" ) FUNC(A_CustomBulletAttack, "XXXXmx" ) FUNC(A_CustomRailgun, "Xxccxxx" ) @@ -1655,6 +1656,14 @@ do_stop: } int paramindex = PrepareStateParameters(&state, numparams); + int paramstart = paramindex; + bool varargs = params[numparams - 1] == '+'; + + if (varargs) + { + StateParameters[paramindex++] = 0; + } + while (*params) { switch(*params) @@ -1763,11 +1772,28 @@ do_stop: v = -1; break; } - StateParameters[paramindex++]=v; + StateParameters[paramindex++] = v; params++; + if (varargs) + { + StateParameters[paramstart]++; + } if (*params) { - if ((islower(*params) || *params=='!') && SC_CheckString(")")) goto endofstate; + if (*params == '+') + { + if (SC_CheckString(")")) + { + goto endofstate; + } + params--; + v = 0; + StateParameters.Push(v); + } + else if ((islower(*params) || *params=='!') && SC_CheckString(")")) + { + goto endofstate; + } ChkCom(); } } diff --git a/src/thingdef_codeptr.cpp b/src/thingdef_codeptr.cpp index 37441cbda..4bb52351c 100644 --- a/src/thingdef_codeptr.cpp +++ b/src/thingdef_codeptr.cpp @@ -405,33 +405,23 @@ static void DoJump(AActor * self, FState * CallingState, int offset) void A_Jump(AActor * self) { FState * CallingState; - int index=CheckIndex(2, &CallingState); + int index = CheckIndex(3, &CallingState); + int maxchance; - if (index>=0 && pr_cajump() < clamp(EvalExpressionI (StateParameters[index], self), 0, 255)) - DoJump(self, CallingState, StateParameters[index+1]); - - if (pStateCall != NULL) pStateCall->Result=false; // Jumps should never set the result for inventory state chains! -} - -//========================================================================== -// -// State jump function -// -//========================================================================== -void A_JumpSet(AActor * self) -{ - FState * CallingState; - int index=CheckIndex(21, &CallingState); - int i; - - if (index>=0 && pr_cajump() < clamp(EvalExpressionI (StateParameters[index], self), 0, 256)) + if (index >= 0 && + StateParameters[index] >= 2 && + (maxchance = clamp(EvalExpressionI (StateParameters[index + 1], self), 0, 256), + maxchance == 256 || pr_cajump() < maxchance)) { - // Find out how many targets are actually used - for (i = 0; i < 20 && StateParameters[index+i+1] != 0; ++i) - { } - DoJump(self, CallingState, StateParameters[index + (pr_cajump() % i) + 1]); + if (StateParameters[index] == 2) + { + DoJump(self, CallingState, StateParameters[index + 2]); + } + else + { + DoJump(self, CallingState, StateParameters[index + (pr_cajump() % (StateParameters[index] - 1)) + 2]); + } } - if (pStateCall != NULL) pStateCall->Result=false; // Jumps should never set the result for inventory state chains! }