- Added Gez's Skulltag feature patch, including:
* BUMPSPECIAL flag: actors with this flag will run their special if collided on by a player
* WEAPON.NOAUTOAIM flag, though it is restricted to attacks that spawn a missile (it will not affect autoaim settings for a hitscan or railgun, and that's deliberate)
* A_FireSTGrenade codepointer, extended to be parameterizable
* The grenade (as the default actor for A_FireSTGrenade)
* Protective armors à la RedArmor: they work with a DamageFactor; for example to recreate the RedArmor from Skulltag, copy its code from skulltag.pk3 but remove the "native" keyword and add DamageFactor "Fire" 0.1 to its properties.
SVN r1661 (trunk)
This commit is contained in:
parent
4fcd64d2c1
commit
523cf6acb2
17 changed files with 154 additions and 23 deletions
|
|
@ -309,6 +309,7 @@ enum
|
|||
MF6_MTHRUSPECIES = 0x00000004, // Missile passes through actors of its shooter's species.
|
||||
MF6_FORCEPAIN = 0x00000008, // forces target into painstate (unless it has the NOPAIN flag)
|
||||
MF6_NOFEAR = 0x00000010, // Not scared of frightening players
|
||||
MF6_BUMPSPECIAL = 0x00000020, // Actor executes its special when being collided (as the ST flag)
|
||||
|
||||
|
||||
// --- mobj.renderflags ---
|
||||
|
|
|
|||
|
|
@ -361,6 +361,34 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMissile)
|
|||
P_SpawnPlayerMissile (self, PClass::FindClass("Rocket"));
|
||||
}
|
||||
|
||||
//
|
||||
// A_FireSTGrenade: not exactly backported from ST, but should work the same
|
||||
//
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireSTGrenade)
|
||||
{
|
||||
player_t *player;
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_CLASS(grenade, 0);
|
||||
if (grenade == NULL) return;
|
||||
|
||||
if (NULL == (player = self->player))
|
||||
{
|
||||
return;
|
||||
}
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
return;
|
||||
}
|
||||
|
||||
// Temporarily raise the pitch to send the grenade slightly upwards
|
||||
fixed_t SavedPlayerPitch = self->pitch;
|
||||
self->pitch -= (1152 << FRACBITS);
|
||||
P_SpawnPlayerMissile(self, grenade);
|
||||
self->pitch = SavedPlayerPitch;
|
||||
}
|
||||
|
||||
//
|
||||
// A_FirePlasma
|
||||
//
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
|||
{
|
||||
// The armor has become useless
|
||||
SavePercent = 0;
|
||||
ArmorType = NAME_None; // Not NAME_BasicArmor.
|
||||
// Now see if the player has some more armor in their inventory
|
||||
// and use it if so. As in Strife, the best armor is used up first.
|
||||
ABasicArmorPickup *best = NULL;
|
||||
|
|
@ -162,6 +163,24 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
|||
}
|
||||
damage = newdamage;
|
||||
}
|
||||
|
||||
// Once the armor has absorbed its part of the damage, then apply its damage factor, if any, to the player
|
||||
if ((damage > 0) && (ArmorType != NAME_None)) // BasicArmor is not going to have any damage factor, so skip it.
|
||||
{
|
||||
// This code is taken and adapted from APowerProtection::ModifyDamage().
|
||||
// The differences include not checking for the NAME_None key (doesn't seem appropriate here),
|
||||
// not using a default value, and of course the way the damage factor info is obtained.
|
||||
const fixed_t *pdf = NULL;
|
||||
DmgFactors *df = PClass::FindClass(ArmorType)->ActorInfo->DamageFactors;
|
||||
if (df != NULL && df->CountUsed() != 0)
|
||||
{
|
||||
pdf = df->CheckKey(damageType);
|
||||
if (pdf != NULL)
|
||||
{
|
||||
damage = newdamage = FixedMul(damage, *pdf);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Inventory != NULL)
|
||||
{
|
||||
Inventory->AbsorbDamage (damage, damageType, newdamage);
|
||||
|
|
|
|||
|
|
@ -1387,7 +1387,7 @@ IMPLEMENT_CLASS (AHealth)
|
|||
|
||||
//===========================================================================
|
||||
//
|
||||
// AHealth :: TryPickup
|
||||
// AHealth :: PickupMessage
|
||||
//
|
||||
//===========================================================================
|
||||
const char *AHealth::PickupMessage ()
|
||||
|
|
|
|||
|
|
@ -317,9 +317,10 @@ enum
|
|||
WIF_POWERED_UP = 0x00000400, // this is a tome-of-power'ed version of its sister
|
||||
WIF_AMMO_CHECKBOTH = 0x00000800, // check for both primary and secondary fire before switching it off
|
||||
WIF_NO_AUTO_SWITCH = 0x00001000, // never switch to this weapon when it's picked up
|
||||
WIF_STAFF2_KICKBACK = 0x00002000, // the powered-up Heretic staff has special kickba
|
||||
WIF_STAFF2_KICKBACK = 0x00002000, // the powered-up Heretic staff has special kickback
|
||||
WIF_NOAUTOAIM = 0x00004000, // this weapon never uses autoaim (useful for ballistic projectiles)
|
||||
|
||||
WIF_CHEATNOTWEAPON = 1<<27, // Give cheat considers this not a weapon (used by Sigil)
|
||||
WIF_CHEATNOTWEAPON = 0x08000000, // Give cheat considers this not a weapon (used by Sigil)
|
||||
|
||||
// Flags used only by bot AI:
|
||||
|
||||
|
|
|
|||
|
|
@ -2957,7 +2957,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
|||
{
|
||||
FName p(FBehavior::StaticLookupString(args[0]));
|
||||
ABasicArmor * armor = (ABasicArmor *) players[args[1]].mo->FindInventory(NAME_BasicArmor);
|
||||
if (armor->ArmorType == p) return 1;
|
||||
if (armor && armor->ArmorType == p) return armor->Amount;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -826,6 +826,13 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
|||
return false;
|
||||
}
|
||||
}
|
||||
// Check for players touching a thing with MF6_BUMPSPECIAL
|
||||
// A blind recreation of what the Skulltag code is probably like.
|
||||
if (tm.thing->player && (thing->flags6 & MF6_BUMPSPECIAL) && thing->special)
|
||||
{
|
||||
LineSpecials[thing->special] (NULL, tm.thing, false, thing->args[0],
|
||||
thing->args[1], thing->args[2], thing->args[3], thing->args[4]);
|
||||
}
|
||||
// Check for missile
|
||||
if (tm.thing->flags & MF_MISSILE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4999,21 +4999,30 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
|
|||
AActor *linetarget;
|
||||
int vrange = nofreeaim? ANGLE_1*35 : 0;
|
||||
|
||||
// see which target is to be aimed at
|
||||
i = 2;
|
||||
do
|
||||
// Note: NOAUTOAIM is implemented only here, and not in the hitscan or rail attack functions.
|
||||
// That is because it is only justified for projectiles affected by gravity, not for other attacks.
|
||||
if (source && source->player && source->player->ReadyWeapon && (source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM))
|
||||
{
|
||||
an = angle + angdiff[i];
|
||||
pitch = P_AimLineAttack (source, an, 16*64*FRACUNIT, &linetarget, vrange);
|
||||
|
||||
if (source->player != NULL &&
|
||||
!nofreeaim &&
|
||||
level.IsFreelookAllowed() &&
|
||||
source->player->userinfo.GetAimDist() <= ANGLE_1/2)
|
||||
// Keep exactly the same angle and pitch as the player's own aim
|
||||
pitch = source->pitch; linetarget = NULL;
|
||||
}
|
||||
else // see which target is to be aimed at
|
||||
{
|
||||
i = 2;
|
||||
do
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (linetarget == NULL && --i >= 0);
|
||||
an = angle + angdiff[i];
|
||||
pitch = P_AimLineAttack (source, an, 16*64*FRACUNIT, &linetarget, vrange);
|
||||
|
||||
if (source->player != NULL &&
|
||||
!nofreeaim &&
|
||||
level.IsFreelookAllowed() &&
|
||||
source->player->userinfo.GetAimDist() <= ANGLE_1/2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (linetarget == NULL && --i >= 0);
|
||||
}
|
||||
|
||||
if (linetarget == NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -535,12 +535,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfArmorType)
|
|||
ACTION_PARAM_START(3);
|
||||
ACTION_PARAM_NAME(Type, 0);
|
||||
ACTION_PARAM_STATE(JumpOffset, 1);
|
||||
ACTION_PARAM_INT(amount, 1);
|
||||
|
||||
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
|
||||
|
||||
ABasicArmor * armor = (ABasicArmor *) self->FindInventory(NAME_BasicArmor);
|
||||
|
||||
if (armor && armor->ArmorType == Type)
|
||||
if (armor && armor->ArmorType == Type && armor->Amount >= amount)
|
||||
ACTION_JUMP(JumpOffset);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -214,6 +214,7 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_FLAG(MF6, MTHRUSPECIES, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, FORCEPAIN, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, NOFEAR, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, BUMPSPECIAL, AActor, flags6),
|
||||
|
||||
// Effect flags
|
||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||
|
|
@ -234,9 +235,12 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_DEPRECATED_FLAG(HERETICBOUNCE),
|
||||
DEFINE_DEPRECATED_FLAG(HEXENBOUNCE),
|
||||
DEFINE_DEPRECATED_FLAG(DOOMBOUNCE),
|
||||
DEFINE_DUMMY_FLAG(NONETID),
|
||||
DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN),
|
||||
DEFINE_DUMMY_FLAG(CLIENTSIDEONLY),
|
||||
|
||||
// Various Skulltag flags that are quite irrelevant to ZDoom
|
||||
DEFINE_DUMMY_FLAG(NONETID), // netcode-based
|
||||
DEFINE_DUMMY_FLAG(ALLOWCLIENTSPAWN), // netcode-based
|
||||
DEFINE_DUMMY_FLAG(CLIENTSIDEONLY), // netcode-based
|
||||
DEFINE_DUMMY_FLAG(EXPLODEONDEATH), // seems useless
|
||||
};
|
||||
|
||||
static FFlagDef InventoryFlags[] =
|
||||
|
|
@ -281,6 +285,7 @@ static FFlagDef WeaponFlags[] =
|
|||
DEFINE_FLAG(WIF, CHEATNOTWEAPON, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, AMMO_CHECKBOTH, AWeapon, WeaponFlags),
|
||||
DEFINE_FLAG(WIF, NOAUTOAIM, AWeapon, WeaponFlags),
|
||||
|
||||
DEFINE_DUMMY_FLAG(NOLMS),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def);
|
|||
//
|
||||
// ParseParameter
|
||||
//
|
||||
// Parses aparameter - either a default in a function declaration
|
||||
// Parses a parameter - either a default in a function declaration
|
||||
// or an argument in a function call.
|
||||
//
|
||||
//==========================================================================
|
||||
|
|
|
|||
|
|
@ -1262,6 +1262,14 @@ DEFINE_CLASS_PROPERTY(pickupsound, S, Inventory)
|
|||
defaults->PickupSound = str;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
// Dummy for Skulltag compatibility...
|
||||
//==========================================================================
|
||||
DEFINE_CLASS_PROPERTY(pickupannouncerentry, S, Inventory)
|
||||
{
|
||||
PROP_STRING_PARM(str, 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//==========================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue