From 688476b9aa2e334a0f824ece754c5b21eec6b0b0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 10 Aug 2006 15:28:12 +0000 Subject: [PATCH] August 10, 2006 (Changes by Graf Zahl) - Fixed: CheckActorInventory stored the return value in the wrong address on the ACS stack. - Fixed: Skin sounds weren't properly restored after a SNDINFO reset. - Added a more flexible ACS ChangeLevel function. It gets passed a level name instead of a level number and has several additional options (e.g. changing skill, starting the map without monsters and clearing the players' inventories. (UNTESTED!) - Changed Thing_Activate so that passing a tid of 0 activates the calling actor. - Changed Thing_Remove so that passing a tid of 0 removes the calling actor. - Added DECORATE parameters to A_Saw. SVN r283 (trunk) --- docs/rh-log.txt | 13 +++++++ src/g_doom/a_doomweaps.cpp | 36 +++++++++++++----- src/g_game.cpp | 28 +++++++++++++- src/g_game.h | 2 +- src/g_level.cpp | 28 ++++++++++++-- src/g_level.h | 4 ++ src/p_acs.cpp | 13 ++++++- src/p_acs.h | 11 ++++++ src/p_lnspec.cpp | 75 ++++++++++++++++++++++++-------------- src/r_things.cpp | 6 +-- src/s_advsound.cpp | 7 +++- src/thingdef.cpp | 2 +- 12 files changed, 176 insertions(+), 49 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index f7bb2b44c..509b7dc16 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,16 @@ +August 10, 2006 (Changes by Graf Zahl) +- Fixed: CheckActorInventory stored the return value in the wrong address + on the ACS stack. +- Fixed: Skin sounds weren't properly restored after a SNDINFO reset. + +August 6, 2006 (Changes by Graf Zahl) +- Added a more flexible ACS ChangeLevel function. It gets passed a level name + instead of a level number and has several additional options (e.g. changing + skill, starting the map without monsters and clearing the players' inventories. +- Changed Thing_Activate so that passing a tid of 0 activates the calling actor. +- Changed Thing_Remove so that passing a tid of 0 removes the calling actor. +- Added DECORATE parameters to A_Saw. + August 2, 2006 - Fixed: The ACS VM made no checks for object files without strings, assuming that if it didn't have any strings, then it didn't matter what it calculated diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index db7223a3c..93cb6d6e0 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -241,8 +241,12 @@ END_DEFAULTS void A_Saw (AActor *actor) { angle_t angle; - int damage; + int damage=0; player_t *player; + + int fullsound; + int hitsound; + const PClass * pufftype = NULL; if (NULL == (player = actor->player)) { @@ -256,25 +260,37 @@ void A_Saw (AActor *actor) return; } - damage = 2 * (pr_saw()%10+1); + int index = CheckIndex (4, NULL); + if (index >= 0) + { + fullsound = StateParameters[index]; + hitsound = StateParameters[index+1]; + damage = EvalExpressionI (StateParameters[index+2], actor); + pufftype = PClass::FindClass ((ENamedName)StateParameters[index+3]); + } + else + { + fullsound = S_FindSound("weapons/sawfull"); + hitsound = S_FindSound("weapons/sawhit"); + } + if (pufftype == NULL) pufftype = RUNTIME_CLASS(ABulletPuff); + if (damage == 0) damage = 2; + + damage *= (pr_saw()%10+1); angle = actor->angle; angle += pr_saw.Random2() << 18; - // use meleerange + 1 so the puff doesn't skip the flash - // [RH] What I think that really means is that they want the puff to show - // up on walls. If the distance to P_LineAttack is <= MELEERANGE, then it - // won't puff the wall, which is why the fist does not create puffs on - // the walls. + // use meleerange + 1 so the puff doesn't skip the flash (i.e. plays all states) P_LineAttack (actor, angle, MELEERANGE+1, P_AimLineAttack (actor, angle, MELEERANGE+1), damage, - MOD_UNKNOWN, RUNTIME_CLASS(ABulletPuff)); + MOD_UNKNOWN, pufftype); if (!linetarget) { - S_Sound (actor, CHAN_WEAPON, "weapons/sawfull", 1, ATTN_NORM); + S_SoundID (actor, CHAN_WEAPON, fullsound, 1, ATTN_NORM); return; } - S_Sound (actor, CHAN_WEAPON, "weapons/sawhit", 1, ATTN_NORM); + S_SoundID (actor, CHAN_WEAPON, hitsound, 1, ATTN_NORM); // turn to face target angle = R_PointToAngle2 (actor->x, actor->y, diff --git a/src/g_game.cpp b/src/g_game.cpp index 24be31458..d3942bf01 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1034,7 +1034,7 @@ void G_Ticker () // G_PlayerFinishLevel // Called when a player completes a level. // -void G_PlayerFinishLevel (int player, EFinishLevelType mode) +void G_PlayerFinishLevel (int player, EFinishLevelType mode, bool resetinventory) { AInventory *item, *next; player_t *p; @@ -1102,6 +1102,32 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode) { // Undo morph P_UndoPlayerMorph (p, true); } + + // Clears the entire inventory and gives back the defaults for starting a game + if (resetinventory) + { + AInventory *inv = p->mo->Inventory; + + while (inv != NULL) + { + AInventory *next = inv->Inventory; + if (!(inv->ItemFlags & IF_UNDROPPABLE)) + { + inv->Destroy (); + } + else if (inv->GetClass() == RUNTIME_CLASS(AHexenArmor)) + { + AHexenArmor *harmor = static_cast (inv); + harmor->Slots[3] = harmor->Slots[2] = harmor->Slots[1] = harmor->Slots[0] = 0; + } + inv = next; + } + p->ReadyWeapon = NULL; + p->PendingWeapon = WP_NOCHANGE; + p->psprites[ps_weapon].state = NULL; + p->psprites[ps_flash].state = NULL; + p->mo->GiveDefaultInventory(); + } } diff --git a/src/g_game.h b/src/g_game.h index 60a87eb66..bb3ae6d69 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -72,7 +72,7 @@ enum EFinishLevelType FINISH_NoHub }; -void G_PlayerFinishLevel (int player, EFinishLevelType mode); +void G_PlayerFinishLevel (int player, EFinishLevelType mode, bool resetinventory); // Adds pitch to consoleplayer's viewpitch and clamps it void G_AddViewPitch (int look); diff --git a/src/g_level.cpp b/src/g_level.cpp index 3ff4110fc..ae8af62b4 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1559,11 +1559,13 @@ BOOL secretexit; static int startpos; // [RH] Support for multiple starts per level extern BOOL NoWipe; // [RH] Don't wipe when travelling in hubs static bool startkeepfacing; // [RH] Support for keeping your facing angle +static bool resetinventory; // Reset the inventory to the player's default for the next level // [RH] The position parameter to these next three functions should // match the first parameter of the single player start spots // that should appear in the next map. -static void goOn (int position, bool keepFacing, bool secret) + +static void goOn (int position, bool keepFacing, bool secret, bool resetinv) { static bool unloading; @@ -1580,6 +1582,8 @@ static void goOn (int position, bool keepFacing, bool secret) startkeepfacing = keepFacing; gameaction = ga_completed; secretexit = secret; + resetinventory = resetinv; + bglobal.End(); //Added by MC: // [RH] Give scripts a chance to do something @@ -1603,7 +1607,7 @@ static void goOn (int position, bool keepFacing, bool secret) void G_ExitLevel (int position, bool keepFacing) { - goOn (position, keepFacing, false); + goOn (position, keepFacing, false, false); } // Here's for the german edition. @@ -1612,7 +1616,23 @@ void G_SecretExitLevel (int position) // [RH] Check for secret levels is done in // G_DoCompleted() - goOn (position, false, true); + goOn (position, false, true, false); +} + +void G_ChangeLevel(const char * levelname, int position, bool keepFacing, int nextSkill, + bool nointermission, bool resetinventory, bool nomonsters) +{ + strncpy (level.nextmap, levelname, 8); + level.nextmap[8] = 0; + + if (nextSkill != -1) NextSkill = nextSkill; + + if (!nomonsters) dmflags = dmflags & ~DF_NO_MONSTERS; + else dmflags = dmflags | DF_NO_MONSTERS; + + if (nointermission) level.flags |= LEVEL_NOINTERMISSION; + + goOn(position, keepFacing, false, resetinventory); } void G_DoCompleted (void) @@ -1738,7 +1758,7 @@ void G_DoCompleted (void) { if (playeringame[i]) { // take away appropriate inventory - G_PlayerFinishLevel (i, mode); + G_PlayerFinishLevel (i, mode, resetinventory); } } diff --git a/src/g_level.h b/src/g_level.h index c7711aea3..4f99693c4 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -301,6 +301,10 @@ void G_DeferedInitNew (char *mapname); void G_ExitLevel (int position, bool keepFacing); void G_SecretExitLevel (int position); + +void G_ChangeLevel(const char * levelname, int position, bool keepFacing, int nextSkill, + bool showintermission, bool resetinventory, bool nomonsters); + void G_SetForEndGame (char *nextmap); void G_StartTravel (); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 19ca624c5..5980ae3dc 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -4176,7 +4176,7 @@ int DLevelScript::RunScript () break; case PCD_CHECKACTORINVENTORY: - STACK(1) = CheckInventory (SingleActorFromTID(STACK(2), NULL), + STACK(2) = CheckInventory (SingleActorFromTID(STACK(2), NULL), FBehavior::StaticLookupString (STACK(1))); sp--; break; @@ -4887,6 +4887,17 @@ int DLevelScript::RunScript () } } sp -= 1; + + case PCD_CHANGELEVEL: + { + int flags = STACK(2); + G_ChangeLevel(FBehavior::StaticLookupString(STACK(4)), STACK(3), + !!(flags & CHANGELEVEL_KEEPFACING), STACK(1), + !!(flags & CHANGELEVEL_NOINTERMISSION), + !!(flags & CHANGELEVEL_RESETINVENTORY), + !!(flags & CHANGELEVEL_NOMONSTERS)); + sp -= 4; + } break; } diff --git a/src/p_acs.h b/src/p_acs.h index 230c2fe28..081f64f06 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -532,6 +532,7 @@ public: PCD_RSGLOBALARRAY, //[MW] end my p-codes PCD_GETPLAYERINFO, // [GRB] + PCD_CHANGELEVEL, PCODE_COMMAND_COUNT }; @@ -611,6 +612,16 @@ public: SCRIPT_ModulusBy0, }; + enum + { + CHANGELEVEL_KEEPFACING = 1, + CHANGELEVEL_RESETINVENTORY = 2, + CHANGELEVEL_NOMONSTERS = 4, + CHANGELEVEL_CHANGESKILL = 8, + CHANGELEVEL_NOINTERMISSION = 16 + }; + + DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr *code, FBehavior *module, bool backSide, int arg0, int arg1, int arg2, int always, bool delay); ~DLevelScript (); diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 312dd8544..14c8a189d 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -983,22 +983,31 @@ FUNC(LS_HealThing) FUNC(LS_Thing_Activate) // Thing_Activate (tid) { - AActor *actor; - FActorIterator iterator (arg0); - int count = 0; - - actor = iterator.Next (); - while (actor) + if (arg0 != 0) { - // Actor might remove itself as part of activation, so get next - // one before activating it. - AActor *temp = iterator.Next (); - actor->Activate (it); - actor = temp; - count++; - } + AActor *actor; + FActorIterator iterator (arg0); + int count = 0; - return count != 0; + actor = iterator.Next (); + while (actor) + { + // Actor might remove itself as part of activation, so get next + // one before activating it. + AActor *temp = iterator.Next (); + actor->Activate (it); + actor = temp; + count++; + } + + return count != 0; + } + else if (it != NULL) + { + it->Activate(it); + return true; + } + return false; } FUNC(LS_Thing_Deactivate) @@ -1022,26 +1031,38 @@ FUNC(LS_Thing_Deactivate) return count != 0; } +static void RemoveThing(AActor * actor) +{ + // Don't remove live players. + if (actor->player == NULL || actor != actor->player->mo) + { + // be friendly to the level statistics. ;) + if (actor->CountsAsKill() && actor->health > 0) level.total_monsters--; + if (actor->flags&MF_COUNTITEM) level.total_items--; + actor->Destroy (); + } +} + FUNC(LS_Thing_Remove) // Thing_Remove (tid) { - FActorIterator iterator (arg0); - AActor *actor; - - actor = iterator.Next (); - while (actor) + if (arg0 != 0) { - AActor *temp = iterator.Next (); + FActorIterator iterator (arg0); + AActor *actor; - // Don't remove live players. - if (actor->player == NULL || actor != actor->player->mo) + actor = iterator.Next (); + while (actor) { - // be friendly to the level statistics. ;) - if (actor->CountsAsKill() && actor->health > 0) level.total_monsters--; - if (actor->flags&MF_COUNTITEM) level.total_items--; - actor->Destroy (); + AActor *temp = iterator.Next (); + + RemoveThing(actor); + actor = temp; } - actor = temp; + } + else if (it != NULL) + { + RemoveThing(it); } return true; diff --git a/src/r_things.cpp b/src/r_things.cpp index 6f380905e..699096ea9 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -574,11 +574,11 @@ void R_InitSkins (void) if (stricmp (key, "*pain") == 0) { // Replace all pain sounds in one go aliasid = S_AddPlayerSound (skins[i].name, skins[i].gender, - playersoundrefs[0], lump); + playersoundrefs[0], lump, true); for (int l = 3; l > 0; --l) { S_AddPlayerSoundExisting (skins[i].name, skins[i].gender, - playersoundrefs[l], aliasid); + playersoundrefs[l], aliasid, true); } } else @@ -586,7 +586,7 @@ void R_InitSkins (void) int sndref = S_FindSoundNoHash (key); if (sndref != 0) { - S_AddPlayerSound (skins[i].name, skins[i].gender, sndref, lump); + S_AddPlayerSound (skins[i].name, skins[i].gender, sndref, lump, true); } } } diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index ede1cb907..111b5c218 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -145,7 +145,7 @@ struct FMusicVolume // This is used to recreate the skin sounds after reloading SNDINFO due to a changed local one. struct FSavedPlayerSoundInfo { - const char * pclass; + FName pclass; int gender; int refid; int lumpnum; @@ -523,6 +523,8 @@ int S_AddPlayerSound (const char *pclass, int gender, int refid, int lumpnum, bo PlayerSounds[soundlist + S_sfx[refid].link] = id; + Printf("Player sound %s: Classnum %d Gender %d, Refid %d, Lump %d, fromskin %d\n", pclass, classnum, gender, refid, lumpnum, fromskin); + if (fromskin) S_SavePlayerSound(pclass, gender, refid, lumpnum, false); return id; @@ -543,6 +545,9 @@ int S_AddPlayerSoundExisting (const char *pclass, int gender, int refid, PlayerSounds[soundlist + S_sfx[refid].link] = aliasto; + + Printf("Player alias %s: Classnum %d Gender %d, Refid %d, Aliasto %d, fromskin %d\n", pclass, classnum, gender, refid, aliasto, fromskin); + if (fromskin) S_SavePlayerSound(pclass, gender, refid, aliasto, true); return aliasto; diff --git a/src/thingdef.cpp b/src/thingdef.cpp index 19dcf156c..39a4a2edf 100644 --- a/src/thingdef.cpp +++ b/src/thingdef.cpp @@ -645,7 +645,7 @@ AFuncDesc AFTable[]= FUNC(A_Punch, NULL) FUNC(A_CheckReload, NULL) FUNC(A_GunFlash, NULL) - FUNC(A_Saw, NULL) + FUNC(A_Saw, "ssxm") // DECORATE specific functions FUNC(A_BulletAttack, NULL)