mirror of
https://github.com/ZDoom/gzdoom-last-svn.git
synced 2025-05-30 17:00:48 +00:00
* Updated to ZDoom r3532:
- Added Thomas's patch to add a Pufftype parameter to A_Explode. - Expanded 'info' CCMD to also print the TID. - Added Xaser's weapon patch to check +reload and +zoom in A_WeaponReady. - Added Xaser's modified version of kgsws's railgun enhancements patch. - Added DavidPH's A_FaceTarget with pitch submission. - Added NOTAUTOAIMED patch but did not set it for Heretic's pod. - Added FDARI's submission for A_CustomMissile options. - Added patch to have D'Sparil transfer his translations to his second state and the teleport effect. - Fixed TArray compilation issue with GCC 4.7. - Added FDARI's Default/global damagetype properties submission. - Fixed ammo usage issues with Dehacked modified weapons that switch attack code pointers. Unless Dehacked specifies an 'ammo use' value for a weapon any Dehacked modified weapon determines ammo use by attack function, like Doom did originally, and not by the weapon's AmmoUse property. This also addresses that the Cells/BFG shot value always modified the BFG itself. - Fixed: A_Saw depleted ammo after the attack so it still went through with it, even though it was out of ammo. - Fixed: The bounce on actors check handled infinite bouncers (bouncecount == 0) incorrectly. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@1348 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
parent
0d15a59cc2
commit
f79b8147d9
34 changed files with 675 additions and 122 deletions
|
@ -331,6 +331,7 @@ enum
|
|||
MF6_POISONALWAYS = 0x04000000, // Always apply poison, even when target can't take the damage.
|
||||
MF6_DOHARMSPECIES = 0x08000000, // Do hurt one's own species with projectiles.
|
||||
MF6_INTRYMOVE = 0x10000000, // Executing P_TryMove
|
||||
MF6_NOTAUTOAIMED = 0x20000000, // Do not subject actor to player autoaim.
|
||||
|
||||
// --- mobj.renderflags ---
|
||||
|
||||
|
|
|
@ -162,6 +162,41 @@ struct CodePointerAlias
|
|||
};
|
||||
static TArray<CodePointerAlias> MBFCodePointers;
|
||||
|
||||
struct AmmoPerAttack
|
||||
{
|
||||
actionf_p func;
|
||||
int ammocount;
|
||||
};
|
||||
|
||||
DECLARE_ACTION(A_Punch)
|
||||
DECLARE_ACTION(A_FirePistol)
|
||||
DECLARE_ACTION(A_FireShotgun)
|
||||
DECLARE_ACTION(A_FireShotgun2)
|
||||
DECLARE_ACTION(A_FireCGun)
|
||||
DECLARE_ACTION(A_FireMissile)
|
||||
DECLARE_ACTION_PARAMS(A_Saw)
|
||||
DECLARE_ACTION(A_FirePlasma)
|
||||
DECLARE_ACTION(A_FireBFG)
|
||||
DECLARE_ACTION(A_FireOldBFG)
|
||||
DECLARE_ACTION(A_FireRailgun)
|
||||
|
||||
// Default ammo use of the various weapon attacks
|
||||
static AmmoPerAttack AmmoPerAttacks[] = {
|
||||
{ AF_A_Punch, 0},
|
||||
{ AF_A_FirePistol, 1},
|
||||
{ AF_A_FireShotgun, 1},
|
||||
{ AF_A_FireShotgun2, 2},
|
||||
{ AF_A_FireCGun, 1},
|
||||
{ AF_A_FireMissile, 1},
|
||||
{ AFP_A_Saw, 0},
|
||||
{ AF_A_FirePlasma, 1},
|
||||
{ AF_A_FireBFG, -1}, // uses deh.BFGCells
|
||||
{ AF_A_FireOldBFG, 1},
|
||||
{ AF_A_FireRailgun, 1},
|
||||
{ NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
// Miscellaneous info that used to be constant
|
||||
DehInfo deh =
|
||||
{
|
||||
|
@ -183,6 +218,7 @@ DehInfo deh =
|
|||
255, // Rocket explosion style, 255=use cvar
|
||||
FRACUNIT*2/3, // Rocket explosion alpha
|
||||
false, // .NoAutofreeze
|
||||
40, // BFG cells per shot
|
||||
};
|
||||
|
||||
// Doom identified pickup items by their sprites. ZDoom prefers to use their
|
||||
|
@ -1589,6 +1625,7 @@ static int PatchWeapon (int weapNum)
|
|||
else if (stricmp (Line1, "Ammo use") == 0 || stricmp (Line1, "Ammo per shot") == 0)
|
||||
{
|
||||
info->AmmoUse1 = val;
|
||||
info->flags6 |= MF6_INTRYMOVE; // flag the weapon for postprocessing (reuse a flag that can't be set by external means)
|
||||
}
|
||||
else if (stricmp (Line1, "Min ammo") == 0)
|
||||
{
|
||||
|
@ -1742,7 +1779,7 @@ static int PatchMisc (int dummy)
|
|||
{
|
||||
if (stricmp (Line1, "BFG Cells/Shot") == 0)
|
||||
{
|
||||
((AWeapon*)GetDefaultByName ("BFG9000"))->AmmoUse1 = atoi (Line2);
|
||||
deh.BFGCells = atoi (Line2);
|
||||
}
|
||||
else if (stricmp (Line1, "Rocket Explosion Style") == 0)
|
||||
{
|
||||
|
@ -2500,8 +2537,6 @@ static void UnloadDehSupp ()
|
|||
BitNames.ShrinkToFit();
|
||||
StyleNames.Clear();
|
||||
StyleNames.ShrinkToFit();
|
||||
WeaponNames.Clear();
|
||||
WeaponNames.ShrinkToFit();
|
||||
AmmoNames.Clear();
|
||||
AmmoNames.ShrinkToFit();
|
||||
|
||||
|
@ -2794,6 +2829,7 @@ static bool LoadDehSupp ()
|
|||
}
|
||||
else if (sc.Compare("WeaponNames"))
|
||||
{
|
||||
WeaponNames.Clear(); // This won't be cleared by UnloadDEHSupp so we need to do it here explicitly
|
||||
sc.MustGetStringName("{");
|
||||
while (!sc.CheckString("}"))
|
||||
{
|
||||
|
@ -2900,6 +2936,55 @@ void FinishDehPatch ()
|
|||
StateMap.ShrinkToFit();
|
||||
TouchedActors.Clear();
|
||||
TouchedActors.ShrinkToFit();
|
||||
|
||||
// Now it gets nasty: We have to fiddle around with the weapons' ammo use info to make Doom's original
|
||||
// ammo consumption work as intended.
|
||||
|
||||
for(unsigned i = 0; i < WeaponNames.Size(); i++)
|
||||
{
|
||||
AWeapon *weap = (AWeapon*)GetDefaultByType(WeaponNames[i]);
|
||||
bool found = false;
|
||||
if (weap->flags6 & MF6_INTRYMOVE)
|
||||
{
|
||||
// Weapon sets an explicit amount of ammo to use so we won't need any special processing here
|
||||
weap->flags6 &= ~MF6_INTRYMOVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
weap->WeaponFlags |= WIF_DEHAMMO;
|
||||
weap->AmmoUse1 = 0;
|
||||
// to allow proper checks in CheckAmmo we have to find the first attack pointer in the Fire sequence
|
||||
// and set its default ammo use as the weapon's AmmoUse1.
|
||||
|
||||
TMap<FState*, bool> StateVisited;
|
||||
|
||||
FState *state = WeaponNames[i]->ActorInfo->FindState(NAME_Fire);
|
||||
while (state != NULL)
|
||||
{
|
||||
bool *check = StateVisited.CheckKey(state);
|
||||
if (check != NULL && *check)
|
||||
{
|
||||
break; // State has already been checked so we reached a loop
|
||||
}
|
||||
StateVisited[state] = true;
|
||||
for(unsigned j = 0; AmmoPerAttacks[j].func != NULL; j++)
|
||||
{
|
||||
if (state->ActionFunc == AmmoPerAttacks[j].func)
|
||||
{
|
||||
found = true;
|
||||
int use = AmmoPerAttacks[j].ammocount;
|
||||
if (use < 0) use = deh.BFGCells;
|
||||
weap->AmmoUse1 = use;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
state = state->GetNextState();
|
||||
}
|
||||
}
|
||||
}
|
||||
WeaponNames.Clear();
|
||||
WeaponNames.ShrinkToFit();
|
||||
}
|
||||
|
||||
void ModifyDropAmount(AInventory *inv, int dropamount);
|
||||
|
|
|
@ -90,8 +90,8 @@ typedef enum
|
|||
BT_CROUCH = 1<<3,
|
||||
BT_TURN180 = 1<<4,
|
||||
BT_ALTATTACK = 1<<5, // Press your other "Fire".
|
||||
BT_RELOAD = 1<<6, // Not connected to anything at the moment.
|
||||
BT_ZOOM = 1<<7, // Neither is this.
|
||||
BT_RELOAD = 1<<6, // [XA] Reload key. Causes state jump in A_WeaponReady.
|
||||
BT_ZOOM = 1<<7, // [XA] Zoom key. Ditto.
|
||||
|
||||
// The rest are all ignored by the play simulation and are for scripts.
|
||||
BT_SPEED = 1<<8,
|
||||
|
|
|
@ -205,6 +205,8 @@ typedef enum
|
|||
CF_WEAPONREADYALT = 1 << 25, // Weapon can fire its secondary attack
|
||||
CF_WEAPONSWITCHOK = 1 << 26, // It is okay to switch away from this weapon
|
||||
CF_BUDDHA = 1 << 27, // [SP] Buddha mode - take damage, but don't die
|
||||
CF_WEAPONRELOADOK = 1 << 28, // [XA] Okay to reload this weapon.
|
||||
CF_WEAPONZOOMOK = 1 << 29, // [XA] Okay to use weapon zoom function.
|
||||
} cheat_t;
|
||||
|
||||
#define WPIECE1 1
|
||||
|
|
|
@ -230,6 +230,7 @@ struct DehInfo
|
|||
BYTE ExplosionStyle;
|
||||
fixed_t ExplosionAlpha;
|
||||
int NoAutofreeze;
|
||||
int BFGCells;
|
||||
};
|
||||
extern DehInfo deh;
|
||||
EXTERN_CVAR (Int, infighting)
|
||||
|
|
|
@ -36,7 +36,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Punch)
|
|||
if (self->player != NULL)
|
||||
{
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL)
|
||||
if (weapon != NULL && !(weapon->WeaponFlags & WIF_DEHAMMO))
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
return;
|
||||
|
@ -78,7 +78,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePistol)
|
|||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return;
|
||||
|
||||
P_SetPsprite (self->player, ps_flash, weapon->FindState(NAME_Flash));
|
||||
|
@ -144,17 +144,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
|
|||
angle = self->angle + (pr_saw.Random2() * (Spread_XY / 255));
|
||||
slope = P_AimLineAttack (self, angle, Range, &linetarget) + (pr_saw.Random2() * (Spread_Z / 255));
|
||||
|
||||
P_LineAttack (self, angle, Range,
|
||||
slope, damage,
|
||||
NAME_None, pufftype);
|
||||
|
||||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if ((weapon != NULL) && !(Flags & SF_NOUSEAMMO) && !(!linetarget && (Flags & SF_NOUSEAMMOMISS)))
|
||||
if ((weapon != NULL) && !(Flags & SF_NOUSEAMMO) && !(!linetarget && (Flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO))
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
return;
|
||||
}
|
||||
|
||||
P_LineAttack (self, angle, Range, slope, damage, NAME_None, pufftype);
|
||||
|
||||
if (!linetarget)
|
||||
{
|
||||
if ((Flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64))
|
||||
|
@ -224,7 +222,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun)
|
|||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return;
|
||||
P_SetPsprite (player, ps_flash, weapon->FindState(NAME_Flash));
|
||||
}
|
||||
|
@ -255,7 +253,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireShotgun2)
|
|||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 2))
|
||||
return;
|
||||
P_SetPsprite (player, ps_flash, weapon->FindState(NAME_Flash));
|
||||
}
|
||||
|
@ -360,7 +358,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCGun)
|
|||
AWeapon *weapon = player->ReadyWeapon;
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return;
|
||||
|
||||
S_Sound (self, CHAN_WEAPON, "weapons/chngun", 1, ATTN_NORM);
|
||||
|
@ -401,7 +399,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMissile)
|
|||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return;
|
||||
}
|
||||
P_SpawnPlayerMissile (self, PClass::FindClass("Rocket"));
|
||||
|
@ -449,7 +447,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePlasma)
|
|||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return;
|
||||
|
||||
FState *flash = weapon->FindState(NAME_Flash);
|
||||
|
@ -478,7 +476,7 @@ static void FireRailgun(AActor *self, int RailOffset)
|
|||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return;
|
||||
|
||||
FState *flash = weapon->FindState(NAME_Flash);
|
||||
|
@ -530,7 +528,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBFG)
|
|||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, deh.BFGCells))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -623,7 +621,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG)
|
|||
AWeapon *weapon = self->player->ReadyWeapon;
|
||||
if (weapon != NULL)
|
||||
{
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire))
|
||||
if (!weapon->DepleteAmmo (weapon->bAltFire, true, 1))
|
||||
return;
|
||||
}
|
||||
self->player->extralight = 2;
|
||||
|
|
|
@ -117,6 +117,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcererRise)
|
|||
|
||||
self->flags &= ~MF_SOLID;
|
||||
mo = Spawn("Sorcerer2", self->x, self->y, self->z, ALLOW_REPLACE);
|
||||
mo->Translation = self->Translation;
|
||||
mo->SetState (mo->FindState("Rise"));
|
||||
mo->angle = self->angle;
|
||||
mo->CopyFriendliness (self, true);
|
||||
|
@ -148,6 +149,7 @@ void P_DSparilTeleport (AActor *actor)
|
|||
if (P_TeleportMove (actor, spot->x, spot->y, spot->z, false))
|
||||
{
|
||||
mo = Spawn("Sorcerer2Telefade", prevX, prevY, prevZ, ALLOW_REPLACE);
|
||||
if (mo) mo->Translation = actor->Translation;
|
||||
S_Sound (mo, CHAN_BODY, "misc/teleport", 1, ATTN_NORM);
|
||||
actor->SetState (actor->FindState("Teleport"));
|
||||
S_Sound (actor, CHAN_BODY, "misc/teleport", 1, ATTN_NORM);
|
||||
|
|
|
@ -115,7 +115,7 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
|||
{
|
||||
int saved;
|
||||
|
||||
if (damageType != NAME_Drowning)
|
||||
if (!DamageTypeDefinition::IgnoreArmor(damageType))
|
||||
{
|
||||
int full = MAX(0, MaxFullAbsorb - AbsorbCount);
|
||||
if (damage < full)
|
||||
|
@ -490,7 +490,7 @@ bool AHexenArmor::AddArmorToSlot (AActor *actor, int slot, int amount)
|
|||
|
||||
void AHexenArmor::AbsorbDamage (int damage, FName damageType, int &newdamage)
|
||||
{
|
||||
if (damageType != NAME_Drowning)
|
||||
if (!DamageTypeDefinition::IgnoreArmor(damageType))
|
||||
{
|
||||
fixed_t savedPercent = Slots[0] + Slots[1] + Slots[2] + Slots[3] + Slots[4];
|
||||
|
||||
|
|
|
@ -289,6 +289,8 @@ public:
|
|||
virtual FState *GetReadyState ();
|
||||
virtual FState *GetAtkState (bool hold);
|
||||
virtual FState *GetAltAtkState (bool hold);
|
||||
virtual FState *GetRelState ();
|
||||
virtual FState *GetZoomState ();
|
||||
|
||||
virtual void PostMorphWeapon ();
|
||||
virtual void EndPowerup ();
|
||||
|
@ -299,8 +301,8 @@ public:
|
|||
AltFire,
|
||||
EitherFire
|
||||
};
|
||||
bool CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo=false);
|
||||
bool DepleteAmmo (bool altFire, bool checkEnough=true);
|
||||
bool CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo=false, int ammocount = -1);
|
||||
bool DepleteAmmo (bool altFire, bool checkEnough=true, int ammouse = -1);
|
||||
|
||||
protected:
|
||||
AAmmo *AddAmmo (AActor *other, const PClass *ammotype, int amount);
|
||||
|
@ -326,6 +328,8 @@ enum
|
|||
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_MELEEWEAPON = 0x00008000, // melee weapon. Used by bots and monster AI.
|
||||
WIF_DEHAMMO = 0x00010000, // Uses Doom's original amount of ammo for the respective attack functions so that old DEHACKED patches work as intended.
|
||||
// AmmoUse1 will be set to the first attack's ammo use so that checking for empty weapons still works
|
||||
|
||||
WIF_CHEATNOTWEAPON = 0x08000000, // Give cheat considers this not a weapon (used by Sigil)
|
||||
|
||||
|
|
|
@ -430,11 +430,12 @@ bool AWeapon::ShouldStay ()
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
bool AWeapon::CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo)
|
||||
bool AWeapon::CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo, int ammocount)
|
||||
{
|
||||
int altFire;
|
||||
int count1, count2;
|
||||
int enough, enoughmask;
|
||||
int lAmmoUse1;
|
||||
|
||||
if ((dmflags & DF_INFINITE_AMMO) || (Owner->player->cheats & CF_INFINITEAMMO))
|
||||
{
|
||||
|
@ -457,7 +458,16 @@ bool AWeapon::CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo)
|
|||
count1 = (Ammo1 != NULL) ? Ammo1->Amount : 0;
|
||||
count2 = (Ammo2 != NULL) ? Ammo2->Amount : 0;
|
||||
|
||||
enough = (count1 >= AmmoUse1) | ((count2 >= AmmoUse2) << 1);
|
||||
if (ammocount >= 0 && (WeaponFlags & WIF_DEHAMMO))
|
||||
{
|
||||
lAmmoUse1 = ammocount;
|
||||
}
|
||||
else
|
||||
{
|
||||
lAmmoUse1 = AmmoUse1;
|
||||
}
|
||||
|
||||
enough = (count1 >= lAmmoUse1) | ((count2 >= AmmoUse2) << 1);
|
||||
if (WeaponFlags & (WIF_PRIMARY_USES_BOTH << altFire))
|
||||
{
|
||||
enoughmask = 3;
|
||||
|
@ -492,11 +502,11 @@ bool AWeapon::CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo)
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
bool AWeapon::DepleteAmmo (bool altFire, bool checkEnough)
|
||||
bool AWeapon::DepleteAmmo (bool altFire, bool checkEnough, int ammouse)
|
||||
{
|
||||
if (!((dmflags & DF_INFINITE_AMMO) || (Owner->player->cheats & CF_INFINITEAMMO)))
|
||||
{
|
||||
if (checkEnough && !CheckAmmo (altFire ? AltFire : PrimaryFire, false))
|
||||
if (checkEnough && !CheckAmmo (altFire ? AltFire : PrimaryFire, false, false, ammouse))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -504,7 +514,14 @@ bool AWeapon::DepleteAmmo (bool altFire, bool checkEnough)
|
|||
{
|
||||
if (Ammo1 != NULL)
|
||||
{
|
||||
Ammo1->Amount -= AmmoUse1;
|
||||
if (ammouse >= 0 && (WeaponFlags & WIF_DEHAMMO))
|
||||
{
|
||||
Ammo1->Amount -= ammouse;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ammo1->Amount -= AmmoUse1;
|
||||
}
|
||||
}
|
||||
if ((WeaponFlags & WIF_PRIMARY_USES_BOTH) && Ammo2 != NULL)
|
||||
{
|
||||
|
@ -636,6 +653,28 @@ FState *AWeapon::GetAltAtkState (bool hold)
|
|||
return state;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AWeapon :: GetRelState
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FState *AWeapon::GetRelState ()
|
||||
{
|
||||
return FindState(NAME_Reload);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AWeapon :: GetZoomState
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FState *AWeapon::GetZoomState ()
|
||||
{
|
||||
return FindState(NAME_Zoom);
|
||||
}
|
||||
|
||||
/* Weapon giver ***********************************************************/
|
||||
|
||||
class AWeaponGiver : public AWeapon
|
||||
|
|
82
src/info.cpp
82
src/info.cpp
|
@ -55,7 +55,6 @@ extern void LoadActors ();
|
|||
extern void InitBotStuff();
|
||||
extern void ClearStrifeTypes();
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
@ -545,3 +544,84 @@ CCMD (summonfoe)
|
|||
{
|
||||
SummonActor (DEM_SUMMONFOE, DEM_SUMMONFOE2, argv);
|
||||
}
|
||||
|
||||
|
||||
// Damage type defaults / global settings
|
||||
|
||||
TMap<FName, DamageTypeDefinition> GlobalDamageDefinitions;
|
||||
|
||||
void DamageTypeDefinition::Apply(FName const type)
|
||||
{
|
||||
GlobalDamageDefinitions[type] = *this;
|
||||
}
|
||||
|
||||
DamageTypeDefinition *DamageTypeDefinition::Get(FName const type)
|
||||
{
|
||||
return GlobalDamageDefinitions.CheckKey(type);
|
||||
}
|
||||
|
||||
bool DamageTypeDefinition::IgnoreArmor(FName const type)
|
||||
{
|
||||
if (type == NAME_Drowning) return true;
|
||||
DamageTypeDefinition *dtd = Get(type);
|
||||
if (dtd) return dtd->NoArmor;
|
||||
return false;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// DamageTypeDefinition :: ApplyMobjDamageFactor
|
||||
//
|
||||
// Calculates mobj damage based on original damage, defined damage factors
|
||||
// and damage type.
|
||||
//
|
||||
// If the specific damage type is not defined, the damage factor for
|
||||
// type 'None' will be used (with 1.0 as a default value).
|
||||
//
|
||||
// Globally declared damage types may override or multiply the damage
|
||||
// factor when 'None' is used as a fallback in this function.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int DamageTypeDefinition::ApplyMobjDamageFactor(int damage, FName const type, DmgFactors const * const factors)
|
||||
{
|
||||
if (factors)
|
||||
{
|
||||
// If the actor has named damage factors, look for a specific factor
|
||||
fixed_t const *pdf = factors->CheckKey(type);
|
||||
if (pdf) return FixedMul(damage, *pdf); // type specific damage type
|
||||
|
||||
// If this was nonspecific damage, don't fall back to nonspecific search
|
||||
if (type == NAME_None) return damage;
|
||||
}
|
||||
|
||||
// If this was nonspecific damage, don't fall back to nonspecific search
|
||||
else if (type == NAME_None)
|
||||
{
|
||||
return damage;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal is unsupplied / 1.0, so there's no difference between modifying and overriding
|
||||
DamageTypeDefinition *dtd = Get(type);
|
||||
return dtd ? FixedMul(damage, dtd->DefaultFactor) : damage;
|
||||
}
|
||||
|
||||
{
|
||||
fixed_t const *pdf = factors->CheckKey(NAME_None);
|
||||
// Here we are looking for modifications to untyped damage
|
||||
// If the calling actor defines untyped damage factor, that is contained in "pdf".
|
||||
if (pdf) // normal damage available
|
||||
{
|
||||
DamageTypeDefinition *dtd = Get(type);
|
||||
|
||||
if (dtd)
|
||||
{
|
||||
if (dtd->ReplaceFactor) return FixedMul(damage, dtd->DefaultFactor); // use default instead of untyped factor
|
||||
return FixedMul(damage, FixedMul(*pdf, dtd->DefaultFactor)); // use default as modification of untyped factor
|
||||
}
|
||||
return FixedMul(damage, *pdf); // there was no default, so actor default is used
|
||||
}
|
||||
}
|
||||
return damage;
|
||||
}
|
||||
|
|
27
src/info.h
27
src/info.h
|
@ -44,6 +44,8 @@
|
|||
#include "dobject.h"
|
||||
#include "doomdef.h"
|
||||
|
||||
#include "m_fixed.h"
|
||||
|
||||
struct Baggage;
|
||||
class FScanner;
|
||||
struct FActorInfo;
|
||||
|
@ -185,6 +187,31 @@ typedef TMap<FName, int> PainChanceList;
|
|||
typedef TMap<FName, PalEntry> PainFlashList;
|
||||
typedef TMap<int, FPlayerColorSet> FPlayerColorSetMap;
|
||||
|
||||
|
||||
|
||||
struct DamageTypeDefinition
|
||||
{
|
||||
public:
|
||||
DamageTypeDefinition() { Clear(); }
|
||||
|
||||
fixed_t DefaultFactor;
|
||||
bool ReplaceFactor;
|
||||
bool NoArmor;
|
||||
|
||||
void Apply(FName const type);
|
||||
void Clear()
|
||||
{
|
||||
DefaultFactor = (fixed_t)1;
|
||||
ReplaceFactor = false;
|
||||
NoArmor = false;
|
||||
}
|
||||
|
||||
static DamageTypeDefinition *Get(FName const type);
|
||||
static bool IgnoreArmor(FName const type);
|
||||
static int ApplyMobjDamageFactor(int damage, FName const type, DmgFactors const * const factors);
|
||||
};
|
||||
|
||||
|
||||
struct FActorInfo
|
||||
{
|
||||
static void StaticInit ();
|
||||
|
|
|
@ -198,6 +198,8 @@ xx(AltFire)
|
|||
xx(AltHold)
|
||||
xx(Flash)
|
||||
xx(AltFlash)
|
||||
xx(Reload)
|
||||
xx(Zoom)
|
||||
|
||||
// State names used by ASwitchableDecoration
|
||||
xx(Active)
|
||||
|
|
|
@ -310,11 +310,16 @@ void P_RunEffects ()
|
|||
}
|
||||
|
||||
//
|
||||
// AddParticle
|
||||
// JitterParticle
|
||||
//
|
||||
// Creates a particle with "jitter"
|
||||
//
|
||||
particle_t *JitterParticle (int ttl)
|
||||
{
|
||||
return JitterParticle (ttl, 1.0);
|
||||
}
|
||||
// [XA] Added "drift speed" multiplier setting for enhanced railgun stuffs.
|
||||
particle_t *JitterParticle (int ttl, float drift)
|
||||
{
|
||||
particle_t *particle = NewParticle ();
|
||||
|
||||
|
@ -324,10 +329,10 @@ particle_t *JitterParticle (int ttl)
|
|||
|
||||
// Set initial velocities
|
||||
for (i = 3; i; i--, val++)
|
||||
*val = (FRACUNIT/4096) * (M_Random () - 128);
|
||||
*val = (int)((FRACUNIT/4096) * (M_Random () - 128) * drift);
|
||||
// Set initial accelerations
|
||||
for (i = 3; i; i--, val++)
|
||||
*val = (FRACUNIT/16384) * (M_Random () - 128);
|
||||
*val = (int)((FRACUNIT/16384) * (M_Random () - 128) * drift);
|
||||
|
||||
particle->trans = 255; // fully opaque
|
||||
particle->ttl = ttl;
|
||||
|
@ -580,7 +585,7 @@ void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, i
|
|||
}
|
||||
}
|
||||
|
||||
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, float maxdiff, bool silent)
|
||||
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, float maxdiff, bool silent, const PClass *spawnclass, angle_t angle, bool fullbright, int duration, float sparsity, float drift)
|
||||
{
|
||||
double length, lengthsquared;
|
||||
int steps, i;
|
||||
|
@ -663,10 +668,10 @@ void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end
|
|||
step = dir * 3;
|
||||
|
||||
// Create the outer spiral.
|
||||
if (color1 != -1 && (!r_rail_smartspiral || color2 == -1) && r_rail_spiralsparsity > 0)
|
||||
if (color1 != -1 && (!r_rail_smartspiral || color2 == -1) && r_rail_spiralsparsity > 0 && (spawnclass == NULL))
|
||||
{
|
||||
FVector3 spiral_step = step * r_rail_spiralsparsity;
|
||||
int spiral_steps = steps * r_rail_spiralsparsity;
|
||||
FVector3 spiral_step = step * r_rail_spiralsparsity * sparsity;
|
||||
int spiral_steps = (int)(steps * r_rail_spiralsparsity / sparsity);
|
||||
|
||||
color1 = color1 == 0 ? -1 : ParticleColor(color1);
|
||||
pos = start;
|
||||
|
@ -680,14 +685,16 @@ void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end
|
|||
return;
|
||||
|
||||
p->trans = 255;
|
||||
p->ttl = 35;
|
||||
p->fade = FADEFROMTTL(35);
|
||||
p->ttl = duration;
|
||||
p->fade = FADEFROMTTL(duration);
|
||||
p->size = 3;
|
||||
if(fullbright)
|
||||
p->bright = true;
|
||||
|
||||
tempvec = FMatrix3x3(dir, deg) * extend;
|
||||
p->velx = FLOAT2FIXED(tempvec.X)>>4;
|
||||
p->vely = FLOAT2FIXED(tempvec.Y)>>4;
|
||||
p->velz = FLOAT2FIXED(tempvec.Z)>>4;
|
||||
p->velx = FLOAT2FIXED(tempvec.X * drift)>>4;
|
||||
p->vely = FLOAT2FIXED(tempvec.Y * drift)>>4;
|
||||
p->velz = FLOAT2FIXED(tempvec.Z * drift)>>4;
|
||||
tempvec += pos;
|
||||
p->x = FLOAT2FIXED(tempvec.X);
|
||||
p->y = FLOAT2FIXED(tempvec.Y);
|
||||
|
@ -770,6 +777,21 @@ void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end
|
|||
}
|
||||
}
|
||||
}
|
||||
// create actors
|
||||
if(spawnclass != NULL) {
|
||||
if(sparsity < 1) sparsity = 32;
|
||||
|
||||
FVector3 trail_step = (step / 3) * sparsity;
|
||||
int trail_steps = (int)((steps * 3) / sparsity);
|
||||
|
||||
pos = start;
|
||||
for (i = trail_steps; i; i--)
|
||||
{
|
||||
AActor *thing = Spawn (spawnclass, FLOAT2FIXED(pos.X), FLOAT2FIXED(pos.Y), FLOAT2FIXED(pos.Z), ALLOW_REPLACE);
|
||||
if(thing) thing->angle = angle;
|
||||
pos += trail_step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void P_DisconnectEffect (AActor *actor)
|
||||
|
|
|
@ -65,6 +65,7 @@ struct particle_t
|
|||
WORD tnext;
|
||||
WORD snext;
|
||||
subsector_t * subsector;
|
||||
bool bright;
|
||||
};
|
||||
|
||||
extern particle_t *Particles;
|
||||
|
@ -79,6 +80,7 @@ void P_FindParticleSubsectors ();
|
|||
class AActor;
|
||||
|
||||
particle_t *JitterParticle (int ttl);
|
||||
particle_t *JitterParticle (int ttl, float drift);
|
||||
|
||||
void P_ThinkParticles (void);
|
||||
void P_InitEffects (void);
|
||||
|
@ -86,7 +88,7 @@ void P_RunEffects (void);
|
|||
|
||||
void P_RunEffect (AActor *actor, int effects);
|
||||
|
||||
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, float maxdiff = 0, bool silent = false);
|
||||
void P_DrawRailTrail (AActor *source, const FVector3 &start, const FVector3 &end, int color1, int color2, float maxdiff = 0, bool silent = false, const PClass *spawnclass = NULL, angle_t angle = 0, bool fullbright = false, int duration = 35, float sparsity = 1.0, float drift = 1.0);
|
||||
void P_DrawSplash (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int kind);
|
||||
void P_DrawSplash2 (int count, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int updown, int kind);
|
||||
void P_DisconnectEffect (AActor *actor);
|
||||
|
|
|
@ -2726,7 +2726,7 @@ void A_Chase(AActor *self)
|
|||
// A_FaceTracer
|
||||
//
|
||||
//=============================================================================
|
||||
void A_Face (AActor *self, AActor *other, angle_t max_turn)
|
||||
void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch)
|
||||
{
|
||||
if (!other)
|
||||
return;
|
||||
|
@ -2773,6 +2773,50 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn)
|
|||
self->angle = other_angle;
|
||||
}
|
||||
|
||||
// [DH] Now set pitch. In order to maintain compatibility, this can be
|
||||
// disabled and is so by default.
|
||||
if (max_pitch <= ANGLE_180)
|
||||
{
|
||||
// [DH] Don't need to do proper fixed->double conversion, since the
|
||||
// result is only used in a ratio.
|
||||
double dist_x = self->target->x - self->x;
|
||||
double dist_y = self->target->y - self->y;
|
||||
double dist_z = self->target->z - self->z;
|
||||
double dist = sqrt(dist_x*dist_x + dist_y*dist_y + dist_z*dist_z);
|
||||
|
||||
angle_t other_pitch = rad2bam(asin(dist_z / dist));
|
||||
|
||||
if (max_pitch && (max_pitch < (angle_t)abs(self->pitch - other_pitch)))
|
||||
{
|
||||
if (self->pitch > other_pitch)
|
||||
{
|
||||
if (self->pitch - other_pitch < ANGLE_180)
|
||||
{
|
||||
self->pitch -= max_pitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->pitch += max_pitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (other_pitch - self->pitch < ANGLE_180)
|
||||
{
|
||||
self->pitch += max_pitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->pitch -= max_pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->pitch = other_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
// This will never work well if the turn angle is limited.
|
||||
if (max_turn == 0 && (self->angle == other_angle) && other->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE) )
|
||||
{
|
||||
|
@ -2780,43 +2824,46 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn)
|
|||
}
|
||||
}
|
||||
|
||||
void A_FaceTarget (AActor *self, angle_t max_turn)
|
||||
void A_FaceTarget (AActor *self, angle_t max_turn, angle_t max_pitch)
|
||||
{
|
||||
A_Face(self, self->target, max_turn);
|
||||
A_Face(self, self->target, max_turn, max_pitch);
|
||||
}
|
||||
|
||||
void A_FaceMaster (AActor *self, angle_t max_turn)
|
||||
void A_FaceMaster (AActor *self, angle_t max_turn, angle_t max_pitch)
|
||||
{
|
||||
A_Face(self, self->master, max_turn);
|
||||
A_Face(self, self->master, max_turn, max_pitch);
|
||||
}
|
||||
|
||||
void A_FaceTracer (AActor *self, angle_t max_turn)
|
||||
void A_FaceTracer (AActor *self, angle_t max_turn, angle_t max_pitch)
|
||||
{
|
||||
A_Face(self, self->tracer, max_turn);
|
||||
A_Face(self, self->tracer, max_turn, max_pitch);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget)
|
||||
{
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_ANGLE(max_turn, 0);
|
||||
ACTION_PARAM_ANGLE(max_pitch, 1);
|
||||
|
||||
A_FaceTarget(self, max_turn);
|
||||
A_FaceTarget(self, max_turn, max_pitch);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster)
|
||||
{
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_ANGLE(max_turn, 0);
|
||||
ACTION_PARAM_ANGLE(max_pitch, 1);
|
||||
|
||||
A_FaceMaster(self, max_turn);
|
||||
A_FaceMaster(self, max_turn, max_pitch);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTracer)
|
||||
{
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_ANGLE(max_turn, 0);
|
||||
ACTION_PARAM_ANGLE(max_pitch, 1);
|
||||
|
||||
A_FaceTracer(self, max_turn);
|
||||
A_FaceTracer(self, max_turn, max_pitch);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -72,7 +72,7 @@ DECLARE_ACTION(A_FreezeDeathChunks)
|
|||
DECLARE_ACTION(A_BossDeath)
|
||||
|
||||
void A_Chase(AActor *self);
|
||||
void A_FaceTarget (AActor *actor, angle_t max_turn = 0);
|
||||
void A_FaceTarget (AActor *actor, angle_t max_turn = 0, angle_t max_pitch = ANGLE_270);
|
||||
|
||||
bool A_RaiseMobj (AActor *, fixed_t speed);
|
||||
bool A_SinkMobj (AActor *, fixed_t speed);
|
||||
|
|
|
@ -997,20 +997,12 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
|
|||
|
||||
if (!(flags & DMG_NO_FACTOR))
|
||||
{
|
||||
DmgFactors *df = target->GetClass()->ActorInfo->DamageFactors;
|
||||
if (df != NULL)
|
||||
{
|
||||
fixed_t *pdf = df->CheckFactor(mod);
|
||||
if (pdf != NULL)
|
||||
{
|
||||
damage = FixedMul(damage, *pdf);
|
||||
if (damage <= 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
damage = FixedMul(damage, target->DamageFactor);
|
||||
if (damage < 0)
|
||||
return;
|
||||
damage = DamageTypeDefinition::ApplyMobjDamageFactor(damage, mod, target->GetClass()->ActorInfo->DamageFactors);
|
||||
if (damage <= 0)
|
||||
return;
|
||||
}
|
||||
|
||||
damage = target->TakeSpecialDamage (inflictor, source, damage, mod);
|
||||
|
|
|
@ -453,10 +453,11 @@ void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target,
|
|||
void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch);
|
||||
void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version
|
||||
void P_TraceBleed (int damage, AActor *target); // random direction version
|
||||
void P_RailAttack (AActor *source, int damage, int offset, int color1 = 0, int color2 = 0, float maxdiff = 0, bool silent = false, const PClass *puff = NULL, bool pierce = true, angle_t angleoffset = 0, angle_t pitchoffset = 0); // [RH] Shoot a railgun
|
||||
void P_RailAttack (AActor *source, int damage, int offset, int color1 = 0, int color2 = 0, float maxdiff = 0, bool silent = false, const PClass *puff = NULL, bool pierce = true, angle_t angleoffset = 0, angle_t pitchoffset = 0, fixed_t distance = 0, bool fullbright = false, int duration = 35, float sparsity = 1.0, float drift = 1.0, const PClass *spawnclass = NULL); // [RH] Shoot a railgun
|
||||
bool P_HitFloor (AActor *thing);
|
||||
bool P_HitWater (AActor *thing, sector_t *sec, fixed_t splashx = FIXED_MIN, fixed_t splashy = FIXED_MIN, fixed_t splashz=FIXED_MIN, bool checkabove = false, bool alert = true);
|
||||
void P_CheckSplash(AActor *self, fixed_t distance);
|
||||
|
||||
bool P_CheckMissileSpawn (AActor *missile);
|
||||
void P_PlaySpawnSound(AActor *missile, AActor *spawner);
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
|
||||
CVAR (Bool, cl_bloodsplats, true, CVAR_ARCHIVE)
|
||||
CVAR (Int, sv_smartaim, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
||||
CVAR (Bool, cl_doautoaim, false, CVAR_ARCHIVE)
|
||||
|
||||
static void CheckForPushSpecial (line_t *line, int side, AActor *mobj, bool windowcheck);
|
||||
static void SpawnShootDecal (AActor *t1, const FTraceResults &trace);
|
||||
|
@ -2845,20 +2846,19 @@ bool P_BounceActor (AActor *mo, AActor * BlockingMobj)
|
|||
|| ((BlockingMobj->player == NULL) && (!(BlockingMobj->flags3 & MF3_ISMONSTER)))
|
||||
))
|
||||
{
|
||||
if (mo->bouncecount > 0 && --mo->bouncecount == 0) return false;
|
||||
|
||||
fixed_t speed;
|
||||
if (mo->bouncecount > 0 && --mo->bouncecount > 0)
|
||||
{
|
||||
angle_t angle = R_PointToAngle2 (BlockingMobj->x,
|
||||
BlockingMobj->y, mo->x, mo->y) + ANGLE_1*((pr_bounce()%16)-8);
|
||||
speed = P_AproxDistance (mo->velx, mo->vely);
|
||||
speed = FixedMul (speed, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent
|
||||
mo->angle = angle;
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
mo->velx = FixedMul (speed, finecosine[angle]);
|
||||
mo->vely = FixedMul (speed, finesine[angle]);
|
||||
mo->PlayBounceSound(true);
|
||||
return true;
|
||||
}
|
||||
angle_t angle = R_PointToAngle2 (BlockingMobj->x,
|
||||
BlockingMobj->y, mo->x, mo->y) + ANGLE_1*((pr_bounce()%16)-8);
|
||||
speed = P_AproxDistance (mo->velx, mo->vely);
|
||||
speed = FixedMul (speed, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent
|
||||
mo->angle = angle;
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
mo->velx = FixedMul (speed, finecosine[angle]);
|
||||
mo->vely = FixedMul (speed, finesine[angle]);
|
||||
mo->PlayBounceSound(true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -3089,6 +3089,12 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
|
|||
}
|
||||
dist = FixedMul (attackrange, in->frac);
|
||||
|
||||
// Don't autoaim certain special actors
|
||||
if (!cl_doautoaim && th->flags6 & MF6_NOTAUTOAIMED)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef _3DFLOORS
|
||||
// we must do one last check whether the trace has crossed a 3D floor
|
||||
if (lastsector==th->Sector && th->Sector->e->XFloor.ffloors.Size())
|
||||
|
@ -3838,8 +3844,7 @@ static bool ProcessNoPierceRailHit (FTraceResults &res)
|
|||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void P_RailAttack (AActor *source, int damage, int offset, int color1, int color2, float maxdiff, bool silent, const PClass *puffclass, bool pierce, angle_t angleoffset, angle_t pitchoffset)
|
||||
void P_RailAttack (AActor *source, int damage, int offset, int color1, int color2, float maxdiff, bool silent, const PClass *puffclass, bool pierce, angle_t angleoffset, angle_t pitchoffset, fixed_t distance, bool fullbright, int duration, float sparsity, float drift, const PClass *spawnclass)
|
||||
{
|
||||
fixed_t vx, vy, vz;
|
||||
angle_t angle, pitch;
|
||||
|
@ -3882,8 +3887,7 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color
|
|||
|
||||
int flags;
|
||||
|
||||
AActor *puffDefaults = puffclass == NULL?
|
||||
NULL : GetDefaultByType (puffclass->GetReplacement());
|
||||
AActor *puffDefaults = puffclass == NULL ? NULL : GetDefaultByType (puffclass->GetReplacement());
|
||||
|
||||
if (puffDefaults != NULL && puffDefaults->flags6 & MF6_NOTRIGGER) flags = 0;
|
||||
else flags = TRACE_PCross|TRACE_Impact;
|
||||
|
@ -3891,13 +3895,13 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color
|
|||
if (pierce)
|
||||
{
|
||||
Trace (x1, y1, shootz, source->Sector, vx, vy, vz,
|
||||
8192*FRACUNIT, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace,
|
||||
distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace,
|
||||
flags, ProcessRailHit);
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace (x1, y1, shootz, source->Sector, vx, vy, vz,
|
||||
8192*FRACUNIT, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace,
|
||||
distance, MF_SHOOTABLE, ML_BLOCKEVERYTHING, source, trace,
|
||||
flags, ProcessNoPierceRailHit);
|
||||
}
|
||||
|
||||
|
@ -3922,7 +3926,7 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color
|
|||
if ((RailHits[i].HitActor->flags & MF_NOBLOOD) ||
|
||||
(RailHits[i].HitActor->flags2 & (MF2_DORMANT|MF2_INVULNERABLE)))
|
||||
{
|
||||
spawnpuff = puffclass != NULL;
|
||||
spawnpuff = (puffclass != NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3971,7 +3975,7 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color
|
|||
end.X = FIXED2FLOAT(trace.X);
|
||||
end.Y = FIXED2FLOAT(trace.Y);
|
||||
end.Z = FIXED2FLOAT(trace.Z);
|
||||
P_DrawRailTrail (source, start, end, color1, color2, maxdiff, silent);
|
||||
P_DrawRailTrail (source, start, end, color1, color2, maxdiff, silent, spawnclass, source->angle + angleoffset, fullbright, duration, sparsity, drift);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -5873,6 +5873,7 @@ void PrintMiscActorInfo(AActor * query)
|
|||
(query->special ? LineSpecialsInfo[query->special]->name : "None"),
|
||||
query->args[0], query->args[1], query->args[2], query->args[3],
|
||||
query->args[4], query->special1, query->special2);
|
||||
Printf("\nTID is %d", query->tid);
|
||||
Printf("\nIts coordinates are x: %f, y: %f, z:%f, floor:%f, ceiling:%f.",
|
||||
FIXED2FLOAT(query->x), FIXED2FLOAT(query->y), FIXED2FLOAT(query->z),
|
||||
FIXED2FLOAT(query->floorz), FIXED2FLOAT(query->ceilingz));
|
||||
|
|
139
src/p_pspr.cpp
139
src/p_pspr.cpp
|
@ -95,7 +95,7 @@ void P_SetPsprite (player_t *player, int position, FState *state, bool nofunctio
|
|||
|
||||
if (position == ps_weapon && !nofunction)
|
||||
{ // A_WeaponReady will re-set these as needed
|
||||
player->cheats &= ~(CF_WEAPONREADY | CF_WEAPONREADYALT | CF_WEAPONBOBBING | CF_WEAPONSWITCHOK);
|
||||
player->cheats &= ~(CF_WEAPONREADY | CF_WEAPONREADYALT | CF_WEAPONBOBBING | CF_WEAPONSWITCHOK | CF_WEAPONRELOADOK | CF_WEAPONZOOMOK);
|
||||
}
|
||||
|
||||
psp = &player->psprites[position];
|
||||
|
@ -282,6 +282,66 @@ void P_FireWeaponAlt (player_t *player, FState *state)
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_ReloadWeapon
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void P_ReloadWeapon (player_t *player, FState *state)
|
||||
{
|
||||
AWeapon *weapon;
|
||||
if (!player->isbot && bot_observer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
weapon = player->ReadyWeapon;
|
||||
if (weapon == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == NULL)
|
||||
{
|
||||
state = weapon->GetRelState();
|
||||
}
|
||||
// [XA] don't change state if still null, so if the modder sets
|
||||
// WRF_RELOAD to true but forgets to define the Reload state, the weapon
|
||||
// won't disappear. ;)
|
||||
if (state != NULL)
|
||||
P_SetPsprite (player, ps_weapon, state);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_ZoomWeapon
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void P_ZoomWeapon (player_t *player, FState *state)
|
||||
{
|
||||
AWeapon *weapon;
|
||||
if (!player->isbot && bot_observer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
weapon = player->ReadyWeapon;
|
||||
if (weapon == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == NULL)
|
||||
{
|
||||
state = weapon->GetZoomState();
|
||||
}
|
||||
// [XA] don't change state if still null. Same reasons as above.
|
||||
if (state != NULL)
|
||||
P_SetPsprite (player, ps_weapon, state);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_DropWeapon
|
||||
|
@ -368,6 +428,7 @@ void P_BobWeapon (player_t *player, pspdef_t *psp, fixed_t *x, fixed_t *y)
|
|||
//
|
||||
// Readies a weapon for firing or bobbing with its three ancillary functions,
|
||||
// DoReadyWeaponToSwitch(), DoReadyWeaponToFire() and DoReadyWeaponToBob().
|
||||
// [XA] Added DoReadyWeaponToReload() and DoReadyWeaponToZoom()
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
|
@ -421,12 +482,32 @@ void DoReadyWeaponToBob (AActor * self)
|
|||
}
|
||||
}
|
||||
|
||||
void DoReadyWeaponToReload (AActor * self)
|
||||
{
|
||||
// Prepare for reload action.
|
||||
player_t *player;
|
||||
if (self && (player = self->player))
|
||||
player->cheats |= CF_WEAPONRELOADOK;
|
||||
return;
|
||||
}
|
||||
|
||||
void DoReadyWeaponToZoom (AActor * self)
|
||||
{
|
||||
// Prepare for reload action.
|
||||
player_t *player;
|
||||
if (self && (player = self->player))
|
||||
player->cheats |= CF_WEAPONZOOMOK;
|
||||
return;
|
||||
}
|
||||
|
||||
// This function replaces calls to A_WeaponReady in other codepointers.
|
||||
void DoReadyWeapon(AActor * self)
|
||||
{
|
||||
DoReadyWeaponToBob(self);
|
||||
DoReadyWeaponToFire(self);
|
||||
DoReadyWeaponToSwitch(self);
|
||||
DoReadyWeaponToReload(self);
|
||||
DoReadyWeaponToZoom(self);
|
||||
}
|
||||
|
||||
enum EWRF_Options
|
||||
|
@ -436,6 +517,8 @@ enum EWRF_Options
|
|||
WRF_NoSwitch = 2,
|
||||
WRF_NoPrimary = 4,
|
||||
WRF_NoSecondary = 8,
|
||||
WRF_AllowReload = 16,
|
||||
WRF_AllowZoom = 32,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_WeaponReady)
|
||||
|
@ -447,6 +530,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_WeaponReady)
|
|||
if ((paramflags & WRF_NoFire) != WRF_NoFire) DoReadyWeaponToFire(self,
|
||||
(!(paramflags & WRF_NoPrimary)), (!(paramflags & WRF_NoSecondary)));
|
||||
if (!(paramflags & WRF_NoBob)) DoReadyWeaponToBob(self);
|
||||
if ((paramflags & WRF_AllowReload)) DoReadyWeaponToReload(self);
|
||||
if ((paramflags & WRF_AllowZoom)) DoReadyWeaponToZoom(self);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -520,6 +605,50 @@ void P_CheckWeaponSwitch (player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_CheckWeaponReload
|
||||
//
|
||||
// The player can reload the weapon.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void P_CheckWeaponReload (player_t *player)
|
||||
{
|
||||
AWeapon *weapon = player->ReadyWeapon;
|
||||
|
||||
if (weapon == NULL)
|
||||
return;
|
||||
|
||||
// Check for reload.
|
||||
if ((player->cheats & CF_WEAPONRELOADOK) && (player->cmd.ucmd.buttons & BT_RELOAD))
|
||||
{
|
||||
P_ReloadWeapon (player, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC P_CheckWeaponZoom
|
||||
//
|
||||
// The player can use the weapon's zoom function.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void P_CheckWeaponZoom (player_t *player)
|
||||
{
|
||||
AWeapon *weapon = player->ReadyWeapon;
|
||||
|
||||
if (weapon == NULL)
|
||||
return;
|
||||
|
||||
// Check for zoom.
|
||||
if ((player->cheats & CF_WEAPONZOOMOK) && (player->cmd.ucmd.buttons & BT_ZOOM))
|
||||
{
|
||||
P_ZoomWeapon (player, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// PROC A_ReFire
|
||||
|
@ -892,6 +1021,14 @@ void P_MovePsprites (player_t *player)
|
|||
{
|
||||
P_CheckWeaponFire (player);
|
||||
}
|
||||
if (player->cheats & CF_WEAPONRELOADOK)
|
||||
{
|
||||
P_CheckWeaponReload (player);
|
||||
}
|
||||
if (player->cheats & CF_WEAPONZOOMOK)
|
||||
{
|
||||
P_CheckWeaponZoom (player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2138,6 +2138,9 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade,
|
|||
{
|
||||
vis->Style.colormap = fixedcolormap;
|
||||
}
|
||||
else if(particle->bright) {
|
||||
vis->Style.colormap = map;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Using MulScale15 instead of 16 makes particles slightly more visible
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
// This file was automatically generated by the
|
||||
// updaterevision tool. Do not edit by hand.
|
||||
|
||||
#define ZD_SVN_REVISION_STRING "3520"
|
||||
#define ZD_SVN_REVISION_NUMBER 3520
|
||||
#define ZD_SVN_REVISION_STRING "3532"
|
||||
#define ZD_SVN_REVISION_NUMBER 3532
|
||||
|
|
|
@ -109,5 +109,9 @@ inline double bam2rad(angle_t ang)
|
|||
{
|
||||
return double(ang >> 1) * (PI / ANGLE_90);
|
||||
}
|
||||
inline angle_t rad2bam(double ang)
|
||||
{
|
||||
return angle_t(ang * (double(1<<30) / PI)) << 1;
|
||||
}
|
||||
|
||||
#endif // __TABLES_H__
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <new>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
|
|
@ -368,6 +368,7 @@ struct StateCallData
|
|||
// Macros to handle action functions. These are here so that I don't have to
|
||||
// change every single use in case the parameters change.
|
||||
#define DECLARE_ACTION(name) void AF_##name(AActor *self, AActor *stateowner, FState *, int, StateCallData *);
|
||||
#define DECLARE_ACTION_PARAMS(name) void AFP_##name(AActor *self, AActor *stateowner, FState *, int, StateCallData *);
|
||||
|
||||
// This distinction is here so that CALL_ACTION produces errors when trying to
|
||||
// access a function that requires parameters.
|
||||
|
|
|
@ -729,7 +729,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfArmorType)
|
|||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
|
||||
{
|
||||
ACTION_PARAM_START(7);
|
||||
ACTION_PARAM_START(8);
|
||||
ACTION_PARAM_INT(damage, 0);
|
||||
ACTION_PARAM_INT(distance, 1);
|
||||
ACTION_PARAM_BOOL(hurtSource, 2);
|
||||
|
@ -737,6 +737,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
|
|||
ACTION_PARAM_INT(fulldmgdistance, 4);
|
||||
ACTION_PARAM_INT(nails, 5);
|
||||
ACTION_PARAM_INT(naildamage, 6);
|
||||
ACTION_PARAM_CLASS(pufftype, 7);
|
||||
|
||||
if (damage < 0) // get parameters from metadata
|
||||
{
|
||||
|
@ -761,7 +762,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
|
|||
// Comparing the results of a test wad with Eternity, it seems A_NailBomb does not aim
|
||||
P_LineAttack (self, ang, MISSILERANGE, 0,
|
||||
//P_AimLineAttack (self, ang, MISSILERANGE),
|
||||
naildamage, NAME_None, NAME_BulletPuff);
|
||||
naildamage, NAME_None, pufftype);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -840,6 +841,12 @@ enum CM_Flags
|
|||
CMF_AIMMODE = 3,
|
||||
CMF_TRACKOWNER = 4,
|
||||
CMF_CHECKTARGETDEAD = 8,
|
||||
|
||||
CMF_ABSOLUTEPITCH = 16,
|
||||
CMF_OFFSETPITCH = 32,
|
||||
CMF_SAVEPITCH = 64,
|
||||
|
||||
CMF_ABSOLUTEANGLE = 128
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
|
||||
|
@ -888,22 +895,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
|
|||
self->x+=x;
|
||||
self->y+=y;
|
||||
missile = P_SpawnMissileAngleZSpeed(self, self->z+SpawnHeight, ti, self->angle, 0, GetDefaultByType(ti)->Speed, self, false);
|
||||
self->x-=x;
|
||||
self->x-=x;
|
||||
self->y-=y;
|
||||
|
||||
// It is not necessary to use the correct angle here.
|
||||
// The only important thing is that the horizontal velocity is correct.
|
||||
// Therefore use 0 as the missile's angle and simplify the calculations accordingly.
|
||||
// The actual velocity vector is set below.
|
||||
if (missile)
|
||||
{
|
||||
fixed_t vx = finecosine[pitch>>ANGLETOFINESHIFT];
|
||||
fixed_t vz = finesine[pitch>>ANGLETOFINESHIFT];
|
||||
|
||||
missile->velx = FixedMul (vx, missile->Speed);
|
||||
missile->vely = 0;
|
||||
missile->velz = FixedMul (vz, missile->Speed);
|
||||
}
|
||||
flags |= CMF_ABSOLUTEPITCH;
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -913,11 +908,36 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
|
|||
// Use the actual velocity instead of the missile's Speed property
|
||||
// so that this can handle missiles with a high vertical velocity
|
||||
// component properly.
|
||||
FVector3 velocity (missile->velx, missile->vely, 0);
|
||||
|
||||
fixed_t missilespeed = (fixed_t)velocity.Length();
|
||||
fixed_t missilespeed;
|
||||
|
||||
if ( (CMF_ABSOLUTEPITCH|CMF_OFFSETPITCH) & flags)
|
||||
{
|
||||
if (CMF_OFFSETPITCH & flags)
|
||||
{
|
||||
FVector2 velocity (missile->velx, missile->vely);
|
||||
pitch += R_PointToAngle2(0,0, (fixed_t)velocity.Length(), missile->velz);
|
||||
}
|
||||
ang = pitch >> ANGLETOFINESHIFT;
|
||||
missilespeed = FixedMul(finecosine[ang], missile->Speed);
|
||||
missile->velz = FixedMul(finesine[ang], missile->Speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
FVector2 velocity (missile->velx, missile->vely);
|
||||
missilespeed = (fixed_t)velocity.Length();
|
||||
}
|
||||
|
||||
if (CMF_SAVEPITCH & flags)
|
||||
{
|
||||
missile->pitch = pitch;
|
||||
// In aimmode 0 and 1 without absolutepitch or offsetpitch, the pitch parameter
|
||||
// contains the unapplied parameter. In that case, it is set as pitch without
|
||||
// otherwise affecting the spawned actor.
|
||||
}
|
||||
|
||||
missile->angle = (CMF_ABSOLUTEANGLE & flags) ? Angle : missile->angle + Angle ;
|
||||
|
||||
missile->angle += Angle;
|
||||
ang = missile->angle >> ANGLETOFINESHIFT;
|
||||
missile->velx = FixedMul (missilespeed, finecosine[ang]);
|
||||
missile->vely = FixedMul (missilespeed, finesine[ang]);
|
||||
|
@ -1353,6 +1373,7 @@ enum
|
|||
RAF_SILENT = 1,
|
||||
RAF_NOPIERCE = 2,
|
||||
RAF_EXPLICITANGLE = 4,
|
||||
RAF_FULLBRIGHT = 8
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1362,7 +1383,7 @@ enum
|
|||
//==========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack)
|
||||
{
|
||||
ACTION_PARAM_START(10);
|
||||
ACTION_PARAM_START(15);
|
||||
ACTION_PARAM_INT(Damage, 0);
|
||||
ACTION_PARAM_INT(Spawnofs_XY, 1);
|
||||
ACTION_PARAM_BOOL(UseAmmo, 2);
|
||||
|
@ -1373,6 +1394,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack)
|
|||
ACTION_PARAM_CLASS(PuffType, 7);
|
||||
ACTION_PARAM_ANGLE(Spread_XY, 8);
|
||||
ACTION_PARAM_ANGLE(Spread_Z, 9);
|
||||
ACTION_PARAM_FIXED(Range, 10);
|
||||
ACTION_PARAM_INT(Duration, 11);
|
||||
ACTION_PARAM_FLOAT(Sparsity, 12);
|
||||
ACTION_PARAM_FLOAT(DriftSpeed, 13);
|
||||
ACTION_PARAM_CLASS(SpawnClass, 14);
|
||||
|
||||
if(Range==0) Range=8192*FRACUNIT;
|
||||
if(Duration==0) Duration=35;
|
||||
if(Sparsity==0) Sparsity=1.0;
|
||||
|
||||
if (!self->player) return;
|
||||
|
||||
|
@ -1398,7 +1428,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RailAttack)
|
|||
slope = pr_crailgun.Random2() * (Spread_Z / 255);
|
||||
}
|
||||
|
||||
P_RailAttack (self, Damage, Spawnofs_XY, Color1, Color2, MaxDiff, (Flags & RAF_SILENT), PuffType, (!(Flags & RAF_NOPIERCE)), angle, slope);
|
||||
P_RailAttack (self, Damage, Spawnofs_XY, Color1, Color2, MaxDiff, (Flags & RAF_SILENT), PuffType, (!(Flags & RAF_NOPIERCE)), angle, slope, Range, (Flags & RAF_FULLBRIGHT), Duration, Sparsity, DriftSpeed, SpawnClass);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1416,7 +1446,7 @@ enum
|
|||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
|
||||
{
|
||||
ACTION_PARAM_START(10);
|
||||
ACTION_PARAM_START(15);
|
||||
ACTION_PARAM_INT(Damage, 0);
|
||||
ACTION_PARAM_INT(Spawnofs_XY, 1);
|
||||
ACTION_PARAM_COLOR(Color1, 2);
|
||||
|
@ -1427,6 +1457,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
|
|||
ACTION_PARAM_CLASS(PuffType, 7);
|
||||
ACTION_PARAM_ANGLE(Spread_XY, 8);
|
||||
ACTION_PARAM_ANGLE(Spread_Z, 9);
|
||||
ACTION_PARAM_FIXED(Range, 10);
|
||||
ACTION_PARAM_INT(Duration, 11);
|
||||
ACTION_PARAM_FLOAT(Sparsity, 12);
|
||||
ACTION_PARAM_FLOAT(DriftSpeed, 13);
|
||||
ACTION_PARAM_CLASS(SpawnClass, 14);
|
||||
|
||||
if(Range==0) Range=8192*FRACUNIT;
|
||||
if(Duration==0) Duration=35;
|
||||
if(Sparsity==0) Sparsity=1.0;
|
||||
|
||||
AActor *linetarget;
|
||||
|
||||
|
@ -1507,7 +1546,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
|
|||
slopeoffset = pr_crailgun.Random2() * (Spread_Z / 255);
|
||||
}
|
||||
|
||||
P_RailAttack (self, Damage, Spawnofs_XY, Color1, Color2, MaxDiff, (Flags & RAF_SILENT), PuffType, (!(Flags & RAF_NOPIERCE)), angleoffset, slopeoffset);
|
||||
P_RailAttack (self, Damage, Spawnofs_XY, Color1, Color2, MaxDiff, (Flags & RAF_SILENT), PuffType, (!(Flags & RAF_NOPIERCE)), angleoffset, slopeoffset, Range, (Flags & RAF_FULLBRIGHT), Duration, Sparsity, DriftSpeed, SpawnClass);
|
||||
|
||||
self->x = saved_x;
|
||||
self->y = saved_y;
|
||||
|
|
|
@ -233,6 +233,7 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_FLAG(MF6, DONTCORPSE, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, DOHARMSPECIES, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, POISONALWAYS, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, NOTAUTOAIMED, AActor, flags6),
|
||||
|
||||
// Effect flags
|
||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||
|
|
|
@ -1179,7 +1179,50 @@ static void ParseActor(FScanner &sc)
|
|||
sc.SetCMode (false);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Reads a damage definition
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static void ParseDamageDefinition(FScanner &sc)
|
||||
{
|
||||
sc.SetCMode (true); // This may be 100% irrelevant for such a simple syntax, but I don't know
|
||||
|
||||
// Get DamageType
|
||||
|
||||
sc.MustGetString();
|
||||
FName damageType = sc.String;
|
||||
|
||||
DamageTypeDefinition dtd;
|
||||
|
||||
sc.MustGetToken('{');
|
||||
while (sc.MustGetAnyToken(), sc.TokenType != '}')
|
||||
{
|
||||
if (sc.Compare("FACTOR"))
|
||||
{
|
||||
sc.MustGetFloat();
|
||||
dtd.DefaultFactor = (fixed_t)sc.Float;
|
||||
if (!dtd.DefaultFactor) dtd.ReplaceFactor = true; // Multiply by 0 yields 0: FixedMul(damage, FixedMul(factor, 0)) is more wasteful than FixedMul(factor, 0)
|
||||
}
|
||||
else if (sc.Compare("REPLACEFACTOR"))
|
||||
{
|
||||
dtd.ReplaceFactor = true;
|
||||
}
|
||||
else if (sc.Compare("NOARMOR"))
|
||||
{
|
||||
dtd.NoArmor = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unexpected data (%s) in damagetype definition.", sc.String);
|
||||
}
|
||||
}
|
||||
|
||||
dtd.Apply(damageType);
|
||||
|
||||
sc.SetCMode (false); // (set to true earlier in function)
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -1263,6 +1306,11 @@ void ParseDecorate (FScanner &sc)
|
|||
ParseOldDecoration (sc, DEF_Projectile);
|
||||
break;
|
||||
}
|
||||
else if (sc.Compare("DAMAGETYPE"))
|
||||
{
|
||||
ParseDamageDefinition(sc);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
sc.RestorePos(pos);
|
||||
ParseOldDecoration(sc, DEF_Decoration);
|
||||
|
|
|
@ -69,9 +69,9 @@ ACTOR Actor native //: Thinker
|
|||
action native A_XScream();
|
||||
action native A_Look();
|
||||
action native A_Chase(state melee = "*", state missile = "none", int flags = 0);
|
||||
action native A_FaceTarget(float max_turn = 0);
|
||||
action native A_FaceTracer(float max_turn = 0);
|
||||
action native A_FaceMaster(float max_turn = 0);
|
||||
action native A_FaceTarget(float max_turn = 0, float max_pitch = 270);
|
||||
action native A_FaceTracer(float max_turn = 0, float max_pitch = 270);
|
||||
action native A_FaceMaster(float max_turn = 0, float max_pitch = 270);
|
||||
action native A_PosAttack();
|
||||
action native A_Scream();
|
||||
action native A_SPosAttack();
|
||||
|
@ -196,7 +196,7 @@ ACTOR Actor native //: Thinker
|
|||
action native A_Jump(int chance = 256, state label, ...);
|
||||
action native A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0);
|
||||
action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, int flags = 0);
|
||||
action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, bool aim = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0);
|
||||
action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, bool aim = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none");
|
||||
action native A_JumpIfHealthLower(int health, state label);
|
||||
action native A_JumpIfCloser(float distance, state label);
|
||||
action native A_JumpIfTracerCloser(float distance, state label);
|
||||
|
@ -254,7 +254,7 @@ ACTOR Actor native //: Thinker
|
|||
action native A_Burst(class<Actor> chunktype);
|
||||
action native A_Blast(int flags = 0, int strength = 255, int radius = 255, float speed = 20, class<Actor> blasteffect = "BlastEffect", sound blastsound = "BlastRadius");
|
||||
action native A_RadiusThrust(int force = 128, int distance = -1, bool affectsource = true, int fullthrustdistance = 0);
|
||||
action native A_Explode(int damage = -1, int distance = -1, bool hurtsource = true, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10);
|
||||
action native A_Explode(int damage = -1, int distance = -1, bool hurtsource = true, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10, class<Actor> pufftype = "BulletPuff");
|
||||
action native A_Stop();
|
||||
action native A_Respawn(int flags = 1);
|
||||
action native A_BarrelDestroy();
|
||||
|
|
|
@ -17,6 +17,10 @@ const int CMF_AIMOFFSET = 1;
|
|||
const int CMF_AIMDIRECTION = 2;
|
||||
const int CMF_TRACKOWNER = 4;
|
||||
const int CMF_CHECKTARGETDEAD = 8;
|
||||
const int CMF_ABSOLUTEPITCH = 16;
|
||||
const int CMF_OFFSETPITCH = 32;
|
||||
const int CMF_SAVEPITCH = 64;
|
||||
const int CMF_ABSOLUTEANGLE = 128;
|
||||
|
||||
// Flags for A_CustomBulletAttack
|
||||
const int CBAF_AIMFACING = 1;
|
||||
|
@ -91,6 +95,8 @@ const int WRF_NOFIRE = 12;
|
|||
const int WRF_NOSWITCH = 2;
|
||||
const int WRF_NOPRIMARY = 4;
|
||||
const int WRF_NOSECONDARY = 8;
|
||||
const int WRF_ALLOWRELOAD = 16;
|
||||
const int WRF_ALLOWZOOM = 32;
|
||||
|
||||
// Morph constants
|
||||
const int MRF_ADDSTAMINA = 1;
|
||||
|
@ -110,6 +116,7 @@ const int MRF_UNDOBYDEATHSAVES = 2048;
|
|||
const int RGF_SILENT = 1;
|
||||
const int RGF_NOPIERCING = 2;
|
||||
const int RGF_EXPLICITANGLE = 4;
|
||||
const int RGF_FULLBRIGHT = 8;
|
||||
|
||||
// Flags for A_Mushroom
|
||||
const int MSF_Standard = 0;
|
||||
|
|
|
@ -11,7 +11,7 @@ ACTOR Inventory native
|
|||
action native A_CustomPunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", float range = 0, float lifesteal = 0);
|
||||
action native A_FireBullets(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", int flags = 1, float range = 0);
|
||||
action native A_FireCustomMissile(class<Actor> missiletype, float angle = 0, bool useammo = true, int spawnofs_xy = 0, float spawnheight = 0, bool aimatangle = false, float pitch = 0);
|
||||
action native A_RailAttack(int damage, int spawnofs_xy = 0, int useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0);
|
||||
action native A_RailAttack(int damage, int spawnofs_xy = 0, int useammo = true, color color1 = "", color color2 = "", int flags = 0, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none");
|
||||
action native A_Light(int extralight);
|
||||
action native A_Light0();
|
||||
action native A_Light1();
|
||||
|
|
|
@ -436,6 +436,8 @@ OptionMenu "CustomizeControls"
|
|||
StaticText "Controls", 1
|
||||
Control "Fire", "+attack"
|
||||
Control "Secondary Fire", "+altattack"
|
||||
Control "Weapon Reload", "+reload"
|
||||
Control "Weapon Zoom", "+zoom"
|
||||
Control "Use / Open", "+use"
|
||||
Control "Move forward", "+forward"
|
||||
Control "Move backward", "+back"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue