mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-22 20:21:26 +00:00
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)
This commit is contained in:
parent
2b0fa809c6
commit
688476b9aa
12 changed files with 176 additions and 49 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<AHexenArmor *> (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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
11
src/p_acs.h
11
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 ();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue