- preparations for allowing hitscans through portals.

To allow processing the hit through an arbitrary portal without reference to the portal group table, P_AimLineAttack and P_LineAttack need to pass some more info than just the linetarget.
We need the relative positions of shooter and target within the visual reference of the other to calculate proper angles and we need to know if such a portal was crossed at all, because a few things, e.g. seeker missiles won't work with them.

- fixed setup of target acquisition for the Mage Staff.

The pre-acquired seeker target was never passed to the spawned projectiles.
This commit is contained in:
Christoph Oelckers 2016-03-01 16:38:45 +01:00
parent a16f92c508
commit b4a002a07f
28 changed files with 331 additions and 279 deletions

View File

@ -1397,6 +1397,28 @@ inline fixedvec2 Vec2Angle(fixed_t length, angle_t angle)
void PrintMiscActorInfo(AActor * query);
AActor *P_LinePickActor(AActor *t1, angle_t angle, fixed_t distance, int pitch, ActorFlags actorMask, DWORD wallMask);
// If we want to make P_AimLineAttack capable of handling arbitrary portals, it needs to pass a lot more info than just the linetarget actor.
struct FTranslatedLineTarget
{
AActor *linetarget;
angle_t hitangle;
fixedvec3 targetPosFromSrc;
angle_t targetAngleFromSrc;
fixedvec3 sourcePosFromTarget;
angle_t sourceAngleFromTarget;
bool unlinked; // found by a trace that went through an unlinked portal.
angle_t SourceAngleToTarget() const
{
return R_PointToAngle2(sourcePosFromTarget.x, sourcePosFromTarget.y, linetarget->X(), linetarget->Y());
}
angle_t TargetAngleToSource() const
{
return R_PointToAngle2(linetarget->X(), linetarget->Y(), sourcePosFromTarget.x, sourcePosFromTarget.y);
}
};
#define S_FREETARGMOBJ 1
#endif // __P_MOBJ_H__

View File

@ -2,6 +2,7 @@
#include "actor.h"
#include "d_player.h"
#include "p_pspr.h"
#include "p_local.h"
//==========================================================================
//
@ -34,6 +35,8 @@ AActor *COPY_AAPTR(AActor *origin, int selector)
{
if (selector == AAPTR_DEFAULT) return origin;
FTranslatedLineTarget t;
if (origin)
{
if (origin->player)
@ -41,11 +44,9 @@ AActor *COPY_AAPTR(AActor *origin, int selector)
switch (selector & AAPTR_PLAYER_SELECTORS)
{
case AAPTR_PLAYER_GETTARGET:
{
AActor *gettarget = NULL;
P_BulletSlope(origin, &gettarget);
return gettarget;
}
P_BulletSlope(origin, &t, ALF_PORTALRESTRICT);
return t.linetarget;
case AAPTR_PLAYER_GETCONVERSATION:
return origin->player->ConversationNPC;
}
@ -60,11 +61,8 @@ AActor *COPY_AAPTR(AActor *origin, int selector)
return origin->FriendPlayer ? AAPTR_RESOLVE_PLAYERNUM(origin->FriendPlayer - 1) : NULL;
case AAPTR_GET_LINETARGET:
{
AActor *gettarget = NULL;
P_BulletSlope(origin, &gettarget);
return gettarget;
}
P_BulletSlope(origin, &t, ALF_PORTALRESTRICT);
return t.linetarget;
}
}

View File

@ -872,16 +872,16 @@ CCMD (wdir)
//-----------------------------------------------------------------------------
CCMD(linetarget)
{
AActor *linetarget;
FTranslatedLineTarget t;
if (CheckCheatmode () || players[consoleplayer].mo == NULL) return;
P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->angle,MISSILERANGE, &linetarget, 0);
if (linetarget)
P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->angle,MISSILERANGE, &t, 0);
if (t.linetarget)
{
Printf("Target=%s, Health=%d, Spawnhealth=%d\n",
linetarget->GetClass()->TypeName.GetChars(),
linetarget->health,
linetarget->SpawnHealth());
t.linetarget->GetClass()->TypeName.GetChars(),
t.linetarget->health,
t.linetarget->SpawnHealth());
}
else Printf("No target found\n");
}
@ -889,18 +889,18 @@ CCMD(linetarget)
// As linetarget, but also give info about non-shootable actors
CCMD(info)
{
AActor *linetarget;
FTranslatedLineTarget t;
if (CheckCheatmode () || players[consoleplayer].mo == NULL) return;
P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->angle,MISSILERANGE,
&linetarget, 0, ALF_CHECKNONSHOOTABLE|ALF_FORCENOSMART);
if (linetarget)
&t, 0, ALF_CHECKNONSHOOTABLE|ALF_FORCENOSMART);
if (t.linetarget)
{
Printf("Target=%s, Health=%d, Spawnhealth=%d\n",
linetarget->GetClass()->TypeName.GetChars(),
linetarget->health,
linetarget->SpawnHealth());
PrintMiscActorInfo(linetarget);
t.linetarget->GetClass()->TypeName.GetChars(),
t.linetarget->health,
t.linetarget->SpawnHealth());
PrintMiscActorInfo(t.linetarget);
}
else Printf("No target found. Info cannot find actors that have "
"the NOBLOCKMAP flag or have height/radius of 0.\n");

View File

@ -33,7 +33,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Punch)
angle_t angle;
int damage;
int pitch;
AActor *linetarget;
FTranslatedLineTarget t;
if (self->player != NULL)
{
@ -53,15 +53,15 @@ DEFINE_ACTION_FUNCTION(AActor, A_Punch)
angle = self->angle;
angle += pr_punch.Random2() << 18;
pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget);
pitch = P_AimLineAttack (self, angle, MELEERANGE);
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, LAF_ISMELEEATTACK, &linetarget);
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, LAF_ISMELEEATTACK, &t);
// turn to face target
if (linetarget)
if (t.linetarget)
{
S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
self->angle = self->AngleTo(linetarget);
self->angle = t.SourceAngleToTarget();
}
return 0;
}
@ -133,7 +133,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
angle_t angle;
angle_t slope;
player_t *player;
AActor *linetarget;
FTranslatedLineTarget t;
int actualdamage;
if (NULL == (player = self->player))
@ -159,18 +159,18 @@ 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));
slope = P_AimLineAttack (self, angle, range, &t) + (pr_saw.Random2() * (spread_z / 255));
AWeapon *weapon = self->player->ReadyWeapon;
if ((weapon != NULL) && !(flags & SF_NOUSEAMMO) && !(!linetarget && (flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_WEAPON())
if ((weapon != NULL) && !(flags & SF_NOUSEAMMO) && !(!t.linetarget && (flags & SF_NOUSEAMMOMISS)) && !(weapon->WeaponFlags & WIF_DEHAMMO) && ACTION_CALL_FROM_WEAPON())
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
P_LineAttack (self, angle, range, slope, damage, NAME_Melee, pufftype, false, &linetarget, &actualdamage);
P_LineAttack (self, angle, range, slope, damage, NAME_Melee, pufftype, false, &t, &actualdamage);
if (!linetarget)
if (!t.linetarget)
{
if ((flags & SF_RANDOMLIGHTMISS) && (pr_saw() > 64))
{
@ -197,7 +197,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
}
}
if (lifesteal && !(linetarget->flags5 & MF5_DONTDRAIN))
if (lifesteal && !(t.linetarget->flags5 & MF5_DONTDRAIN))
{
if (flags & SF_STEALARMOR)
{
@ -232,7 +232,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
// turn to face target
if (!(flags & SF_NOTURN))
{
angle = self->AngleTo(linetarget);
angle = t.SourceAngleToTarget();
if (angle - self->angle > ANG180)
{
if (angle - self->angle < (angle_t)(-ANG90 / 20))
@ -643,7 +643,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
int j;
int damage;
angle_t an;
AActor *linetarget;
FTranslatedLineTarget t;
if (spraytype == NULL) spraytype = PClass::FindActor("BFGExtra");
if (numrays <= 0) numrays = 40;
@ -662,18 +662,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
an = self->angle - angle / 2 + angle / numrays*i;
// self->target is the originator (player) of the missile
P_AimLineAttack(self->target, an, distance, &linetarget, vrange);
P_AimLineAttack(self->target, an, distance, &t, vrange);
if (linetarget != NULL)
if (t.linetarget != NULL)
{
AActor *spray = Spawn(spraytype, linetarget->PosPlusZ(linetarget->height >> 2), ALLOW_REPLACE);
AActor *spray = Spawn(spraytype, t.linetarget->PosPlusZ(t.linetarget->height >> 2), ALLOW_REPLACE);
int dmgFlags = 0;
FName dmgType = NAME_BFGSplash;
if (spray != NULL)
{
if (spray->flags6 & MF6_MTHRUSPECIES && self->target->GetSpecies() == linetarget->GetSpecies())
if (spray->flags6 & MF6_MTHRUSPECIES && self->target->GetSpecies() == t.linetarget->GetSpecies())
{
spray->Destroy(); // [MC] Remove it because technically, the spray isn't trying to "hit" them.
continue;
@ -696,8 +696,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
damage = defdamage;
}
int newdam = P_DamageMobj(linetarget, self->target, self->target, damage, dmgType, dmgFlags);
P_TraceBleed(newdam > 0 ? newdam : damage, linetarget, self->target);
int newdam = P_DamageMobj(t.linetarget, self->target, self->target, damage, dmgType, dmgFlags|DMG_USEANGLE, t.SourceAngleToTarget());
P_TraceBleed(newdam > 0 ? newdam : damage, &t, self);
}
}
return 0;

View File

@ -276,16 +276,16 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Saw)
if (self->CheckMeleeRange ())
{
angle_t angle;
AActor *linetarget;
FTranslatedLineTarget t;
damage *= (pr_m_saw()%10+1);
angle = self->angle + (pr_m_saw.Random2() << 18);
P_LineAttack (self, angle, MELEERANGE+1,
P_AimLineAttack (self, angle, MELEERANGE+1, &linetarget), damage,
NAME_Melee, pufftype, false, &linetarget);
P_AimLineAttack (self, angle, MELEERANGE+1), damage,
NAME_Melee, pufftype, false, &t);
if (!linetarget)
if (!t.linetarget)
{
S_Sound (self, CHAN_WEAPON, fullsound, 1, ATTN_NORM);
return 0;
@ -293,7 +293,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_M_Saw)
S_Sound (self, CHAN_WEAPON, hitsound, 1, ATTN_NORM);
// turn to face target
angle = self->AngleTo(linetarget);
angle = t.SourceAngleToTarget();
if (angle - self->angle > ANG180)
{
if (angle - self->angle < (angle_t)(-ANG90/20))
@ -328,7 +328,7 @@ static void MarinePunch(AActor *self, int damagemul)
angle_t angle;
int damage;
int pitch;
AActor *linetarget;
FTranslatedLineTarget t;
if (self->target == NULL)
return;
@ -337,15 +337,14 @@ static void MarinePunch(AActor *self, int damagemul)
A_FaceTarget (self);
angle = self->angle + (pr_m_punch.Random2() << 18);
pitch = P_AimLineAttack (self, angle, MELEERANGE, &linetarget);
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true, &linetarget);
pitch = P_AimLineAttack (self, angle, MELEERANGE);
P_LineAttack (self, angle, MELEERANGE, pitch, damage, NAME_Melee, NAME_BulletPuff, true, &t);
// turn to face target
if (linetarget)
if (t.linetarget)
{
S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
self->angle = self->AngleTo(linetarget);
self->angle = t.SourceAngleToTarget();
}
}

View File

@ -176,7 +176,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1)
int damage;
int slope;
player_t *player;
AActor *linetarget;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
@ -185,11 +185,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1)
damage = 1 + (pr_beakatkpl1()&3);
angle = player->mo->angle;
slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &linetarget);
if (linetarget)
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &t);
if (t.linetarget)
{
player->mo->angle = player->mo->AngleTo(linetarget);
player->mo->angle = t.SourceAngleToTarget();
}
P_PlayPeck (player->mo);
player->chickenPeck = 12;
@ -211,7 +211,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2)
int damage;
int slope;
player_t *player;
AActor *linetarget;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
@ -220,11 +220,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2)
damage = pr_beakatkpl2.HitDice (4);
angle = player->mo->angle;
slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &linetarget);
if (linetarget)
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &t);
if (t.linetarget)
{
player->mo->angle = player->mo->AngleTo(linetarget);
player->mo->angle = t.SourceAngleToTarget();
}
P_PlayPeck (player->mo);
player->chickenPeck = 12;

View File

@ -66,7 +66,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack)
angle_t angle;
int slope;
player_t *player;
AActor *linetarget;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
@ -88,13 +88,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack)
}
angle = self->angle;
angle += pr_sap.Random2() << 18;
slope = P_AimLineAttack (self, angle, MELEERANGE, &linetarget);
P_LineAttack (self, angle, MELEERANGE, slope, damage, NAME_Melee, puff, true, &linetarget);
if (linetarget)
slope = P_AimLineAttack (self, angle, MELEERANGE);
P_LineAttack (self, angle, MELEERANGE, slope, damage, NAME_Melee, puff, true, &t);
if (t.linetarget)
{
//S_StartSound(player->mo, sfx_stfhit);
// turn to face target
self->angle = self->AngleTo(linetarget);
self->angle = t.SourceAngleToTarget();
}
return 0;
}
@ -257,7 +257,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack)
fixed_t dist;
player_t *player;
PClassActor *pufftype;
AActor *linetarget;
FTranslatedLineTarget t;
int actualdamage = 0;
if (NULL == (player = self->player))
@ -290,9 +290,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack)
angle += pr_gatk.Random2() << 18;
pufftype = PClass::FindActor("GauntletPuff1");
}
slope = P_AimLineAttack (self, angle, dist, &linetarget);
P_LineAttack (self, angle, dist, slope, damage, NAME_Melee, pufftype, false, &linetarget, &actualdamage);
if (!linetarget)
slope = P_AimLineAttack (self, angle, dist);
P_LineAttack (self, angle, dist, slope, damage, NAME_Melee, pufftype, false, &t, &actualdamage);
if (!t.linetarget)
{
if (pr_gatk() > 64)
{
@ -316,7 +316,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack)
}
if (power)
{
if (!(linetarget->flags5 & MF5_DONTDRAIN)) P_GiveBody (self, actualdamage>>1);
if (!(t.linetarget->flags5 & MF5_DONTDRAIN)) P_GiveBody (self, actualdamage>>1);
S_Sound (self, CHAN_AUTO, "weapons/gauntletspowhit", 1, ATTN_NORM);
}
else
@ -324,7 +324,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GauntletAttack)
S_Sound (self, CHAN_AUTO, "weapons/gauntletshit", 1, ATTN_NORM);
}
// turn to face target
angle = self->AngleTo(linetarget);
angle = t.SourceAngleToTarget();
if (angle-self->angle > ANG180)
{
if ((int)(angle-self->angle) < -ANG90/20)
@ -594,7 +594,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL2)
AActor *mo;
player_t *player;
AActor *linetarget;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
@ -607,16 +607,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL2)
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
mo = P_SpawnPlayerMissile (self, 0,0,0, RUNTIME_CLASS(AMaceFX4), self->angle, &linetarget);
mo = P_SpawnPlayerMissile (self, 0,0,0, RUNTIME_CLASS(AMaceFX4), self->angle, &t);
if (mo)
{
mo->velx += self->velx;
mo->vely += self->vely;
mo->velz = 2*FRACUNIT+
clamp<fixed_t>(finetangent[FINEANGLES/4-(self->pitch>>ANGLETOFINESHIFT)], -5*FRACUNIT, 5*FRACUNIT);
if (linetarget)
if (t.linetarget && !t.unlinked)
{
mo->tracer = linetarget;
mo->tracer = t.linetarget;
}
}
S_Sound (self, CHAN_WEAPON, "weapons/maceshoot", 1, ATTN_NORM);
@ -637,7 +637,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
AActor *target;
angle_t angle = 0;
bool newAngle;
AActor *linetarget;
FTranslatedLineTarget t;
if ((self->Z() <= self->floorz) && P_HitFloor (self))
{ // Landed in some sort of liquid
@ -671,11 +671,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
angle = 0;
for (i = 0; i < 16; i++)
{
P_AimLineAttack (self, angle, 10*64*FRACUNIT, &linetarget, 0, ALF_NOFRIENDS, NULL, self->target);
if (linetarget && self->target != linetarget)
P_AimLineAttack (self, angle, 10*64*FRACUNIT, &t, 0, ALF_NOFRIENDS|ALF_PORTALRESTRICT, NULL, self->target);
if (t.linetarget && self->target != t.linetarget)
{
self->tracer = linetarget;
angle = self->AngleTo(linetarget);
self->tracer = t.linetarget;
angle = t.SourceAngleToTarget();
newAngle = true;
break;
}
@ -943,7 +943,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL2)
player_t *player;
AActor *MissileActor;
AActor *linetarget;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
@ -955,16 +955,16 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL2)
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
P_SpawnPlayerMissile (self, 0,0,0, RUNTIME_CLASS(AHornRodFX2), self->angle, &linetarget, &MissileActor);
P_SpawnPlayerMissile (self, 0,0,0, RUNTIME_CLASS(AHornRodFX2), self->angle, &t, &MissileActor);
// Use MissileActor instead of the return value from
// P_SpawnPlayerMissile because we need to give info to the mobj
// even if it exploded immediately.
if (MissileActor != NULL)
{
MissileActor->special2 = (int)(player - players);
if (linetarget)
if (t.linetarget && !t.unlinked)
{
MissileActor->tracer = linetarget;
MissileActor->tracer = t.linetarget;
}
S_Sound (MissileActor, CHAN_WEAPON, "weapons/hornrodpowshoot", 1, ATTN_NORM);
}

View File

@ -213,7 +213,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CHolyAttack)
PARAM_ACTION_PROLOGUE;
player_t *player;
AActor *linetarget;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
@ -225,10 +225,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_CHolyAttack)
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
AActor *missile = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindActor("HolyMissile"), self->angle, &linetarget);
if (missile != NULL)
AActor *missile = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindActor("HolyMissile"), self->angle, &t);
if (missile != NULL && !t.unlinked)
{
missile->tracer = linetarget;
missile->tracer = t.linetarget;
}
weapon->CHolyCount = 3;

View File

@ -5,8 +5,6 @@
#include "thingdef/thingdef.h"
*/
extern void AdjustPlayerAngle (AActor *pmo, AActor *linetarget);
static FRandom pr_maceatk ("CMaceAttack");
//===========================================================================
@ -24,7 +22,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CMaceAttack)
int slope;
int i;
player_t *player;
AActor *linetarget;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
@ -39,13 +37,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_CMaceAttack)
for (int j = 1; j >= -1; j -= 2)
{
angle = player->mo->angle + j*i*(ANG45 / 16);
slope = P_AimLineAttack(player->mo, angle, 2 * MELEERANGE, &linetarget);
if (linetarget)
slope = P_AimLineAttack(player->mo, angle, 2 * MELEERANGE, &t);
if (t.linetarget)
{
P_LineAttack(player->mo, angle, 2 * MELEERANGE, slope, damage, NAME_Melee, hammertime, true, &linetarget);
if (linetarget != NULL)
P_LineAttack(player->mo, angle, 2 * MELEERANGE, slope, damage, NAME_Melee, hammertime, true, &t);
if (t.linetarget != NULL)
{
AdjustPlayerAngle(player->mo, linetarget);
AdjustPlayerAngle(player->mo, &t);
goto macedone;
}
}
@ -55,7 +53,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CMaceAttack)
player->mo->weaponspecial = 0;
angle = player->mo->angle;
slope = P_AimLineAttack (player->mo, angle, MELEERANGE, &linetarget);
slope = P_AimLineAttack (player->mo, angle, MELEERANGE);
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, hammertime);
macedone:
return 0;

View File

@ -55,7 +55,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
int slope;
int i;
player_t *player;
AActor *linetarget;
FTranslatedLineTarget t;
PClassActor *puff;
if (NULL == (player = self->player))
@ -73,15 +73,15 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
for (int j = 1; j >= -1; j -= 2)
{
angle = pmo->angle + j*i*(ANG45 / 16);
slope = P_AimLineAttack(pmo, angle, fixed_t(1.5*MELEERANGE), &linetarget, 0, ALF_CHECK3D);
if (linetarget)
slope = P_AimLineAttack(pmo, angle, fixed_t(1.5*MELEERANGE), &t, 0, ALF_CHECK3D);
if (t.linetarget)
{
P_LineAttack(pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, puff, false, &linetarget);
if (linetarget != NULL)
P_LineAttack(pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, puff, false, &t);
if (t.linetarget != NULL)
{
pmo->angle = pmo->AngleTo(linetarget);
if (((linetarget->player && (!linetarget->IsTeammate(pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER)
&& (!(linetarget->flags2&(MF2_DORMANT | MF2_INVULNERABLE))))
pmo->angle = t.SourceAngleToTarget();
if (((t.linetarget->player && (!t.linetarget->IsTeammate(pmo) || level.teamdamage != 0)) || t.linetarget->flags3&MF3_ISMONSTER)
&& (!(t.linetarget->flags2&(MF2_DORMANT | MF2_INVULNERABLE))))
{
newLife = player->health + (damage >> 3);
newLife = newLife > max ? max : newLife;

View File

@ -24,8 +24,6 @@ void A_FAxeCheckReadyG (AActor *actor);
void A_FAxeCheckUpG (AActor *actor);
void A_FAxeAttack (AActor *actor);
extern void AdjustPlayerAngle (AActor *pmo, AActor *linetarget);
// The Fighter's Axe --------------------------------------------------------
class AFWeapAxe : public AFighterWeapon
@ -210,7 +208,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack)
player_t *player;
AWeapon *weapon;
PClassActor *pufftype;
AActor *linetarget;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
@ -239,17 +237,17 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack)
for (int j = 1; j >= -1; j -= 2)
{
angle = pmo->angle + j*i*(ANG45 / 16);
slope = P_AimLineAttack(pmo, angle, AXERANGE, &linetarget);
if (linetarget)
slope = P_AimLineAttack(pmo, angle, AXERANGE, &t);
if (t.linetarget)
{
P_LineAttack(pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true, &linetarget);
if (linetarget != NULL)
P_LineAttack(pmo, angle, AXERANGE, slope, damage, NAME_Melee, pufftype, true, &t);
if (t.linetarget != NULL)
{
if (linetarget->flags3&MF3_ISMONSTER || linetarget->player)
if (t.linetarget->flags3&MF3_ISMONSTER || t.linetarget->player)
{
P_ThrustMobj(linetarget, angle, power);
P_ThrustMobj(t.linetarget, t.hitangle, power);
}
AdjustPlayerAngle(pmo, linetarget);
AdjustPlayerAngle(pmo, &t);
useMana++;
goto axedone;
}
@ -260,7 +258,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack)
pmo->weaponspecial = 0;
angle = pmo->angle;
slope = P_AimLineAttack (pmo, angle, MELEERANGE, &linetarget);
slope = P_AimLineAttack (pmo, angle, MELEERANGE);
P_LineAttack (pmo, angle, MELEERANGE, slope, damage, NAME_Melee, pufftype, true);
axedone:

View File

@ -17,8 +17,6 @@ const fixed_t HAMMER_RANGE = MELEERANGE+MELEERANGE/2;
static FRandom pr_hammeratk ("FHammerAtk");
extern void AdjustPlayerAngle (AActor *pmo, AActor *linetarget);
//============================================================================
//
// A_FHammerAttack
@ -35,7 +33,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack)
int slope;
int i;
player_t *player;
AActor *linetarget;
FTranslatedLineTarget t;
PClassActor *hammertime;
if (NULL == (player = self->player))
@ -50,32 +48,32 @@ DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack)
for (i = 0; i < 16; i++)
{
angle = pmo->angle + i*(ANG45/32);
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE, &linetarget, 0, ALF_CHECK3D);
if (linetarget != NULL)
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE, &t, 0, ALF_CHECK3D);
if (t.linetarget != NULL)
{
P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true, &linetarget);
if (linetarget != NULL)
P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true, &t);
if (t.linetarget != NULL)
{
AdjustPlayerAngle(pmo, linetarget);
if (linetarget->flags3 & MF3_ISMONSTER || linetarget->player)
AdjustPlayerAngle(pmo, &t);
if (t.linetarget->flags3 & MF3_ISMONSTER || t.linetarget->player)
{
P_ThrustMobj(linetarget, angle, power);
P_ThrustMobj(t.linetarget, t.hitangle, power);
}
pmo->weaponspecial = false; // Don't throw a hammer
goto hammerdone;
}
}
angle = pmo->angle-i*(ANG45/32);
slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE, &linetarget, 0, ALF_CHECK3D);
if (linetarget != NULL)
slope = P_AimLineAttack(pmo, angle, HAMMER_RANGE, &t, 0, ALF_CHECK3D);
if (t.linetarget != NULL)
{
P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true, &linetarget);
if (linetarget != NULL)
P_LineAttack(pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true, &t);
if (t.linetarget != NULL)
{
AdjustPlayerAngle(pmo, linetarget);
if (linetarget->flags3 & MF3_ISMONSTER || linetarget->player)
AdjustPlayerAngle(pmo, &t);
if (t.linetarget->flags3 & MF3_ISMONSTER || t.linetarget->player)
{
P_ThrustMobj(linetarget, angle, power);
P_ThrustMobj(t.linetarget, t.hitangle, power);
}
pmo->weaponspecial = false; // Don't throw a hammer
goto hammerdone;
@ -84,7 +82,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack)
}
// didn't find any targets in meleerange, so set to throw out a hammer
angle = pmo->angle;
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE, &linetarget, 0, ALF_CHECK3D);
slope = P_AimLineAttack (pmo, angle, HAMMER_RANGE, NULL, 0, ALF_CHECK3D);
if (P_LineAttack (pmo, angle, HAMMER_RANGE, slope, damage, NAME_Melee, hammertime, true) != NULL)
{
pmo->weaponspecial = false;

View File

@ -25,12 +25,12 @@ static FRandom pr_fpatk ("FPunchAttack");
#define MAX_ANGLE_ADJUST (5*ANGLE_1)
void AdjustPlayerAngle (AActor *pmo, AActor *linetarget)
void AdjustPlayerAngle (AActor *pmo, FTranslatedLineTarget *t)
{
angle_t angle;
int difference;
angle = pmo->AngleTo(linetarget);
angle = t->SourceAngleToTarget();
difference = (int)angle - (int)pmo->angle;
if (abs(difference) > MAX_ANGLE_ADJUST)
{
@ -60,11 +60,11 @@ void AdjustPlayerAngle (AActor *pmo, AActor *linetarget)
static bool TryPunch(APlayerPawn *pmo, angle_t angle, int damage, fixed_t power)
{
PClassActor *pufftype;
AActor *linetarget;
FTranslatedLineTarget t;
int slope;
slope = P_AimLineAttack (pmo, angle, 2*MELEERANGE, &linetarget);
if (linetarget != NULL)
slope = P_AimLineAttack (pmo, angle, 2*MELEERANGE, &t);
if (t.linetarget != NULL)
{
if (++pmo->weaponspecial >= 3)
{
@ -76,15 +76,15 @@ static bool TryPunch(APlayerPawn *pmo, angle_t angle, int damage, fixed_t power)
{
pufftype = PClass::FindActor("PunchPuff");
}
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true, &linetarget);
if (linetarget != NULL)
P_LineAttack (pmo, angle, 2*MELEERANGE, slope, damage, NAME_Melee, pufftype, true, &t);
if (t.linetarget != NULL)
{
if (linetarget->player != NULL ||
(linetarget->Mass != INT_MAX && (linetarget->flags3 & MF3_ISMONSTER)))
if (t.linetarget->player != NULL ||
(t.linetarget->Mass != INT_MAX && (t.linetarget->flags3 & MF3_ISMONSTER)))
{
P_ThrustMobj (linetarget, angle, power);
P_ThrustMobj (t.linetarget, t.hitangle, power);
}
AdjustPlayerAngle (pmo, linetarget);
AdjustPlayerAngle (pmo, &t);
return true;
}
}
@ -131,8 +131,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FPunchAttack)
// didn't find any creatures, so try to strike any walls
pmo->weaponspecial = 0;
AActor *linetarget;
int slope = P_AimLineAttack (pmo, pmo->angle, MELEERANGE, &linetarget);
int slope = P_AimLineAttack (pmo, pmo->angle, MELEERANGE);
P_LineAttack (pmo, pmo->angle, MELEERANGE, slope, damage, NAME_Melee, PClass::FindActor("PunchPuff"), true);
return 0;
}

View File

@ -3,6 +3,8 @@
#include "d_player.h"
void AdjustPlayerAngle(AActor *pmo, FTranslatedLineTarget *t);
class AHolySpirit : public AActor
{
DECLARE_CLASS (AHolySpirit, AActor)

View File

@ -350,7 +350,7 @@ void AZBell::Activate (AActor *activator)
{
if (health > 0)
{
P_DamageMobj (this, activator, activator, 10, NAME_Melee); // 'ring' the bell
P_DamageMobj (this, activator, activator, 10, NAME_Melee, DMG_THRUSTLESS); // 'ring' the bell
}
}

View File

@ -60,7 +60,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireConePL1)
AActor *mo;
bool conedone=false;
player_t *player;
AActor *linetarget;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
@ -79,10 +79,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireConePL1)
for (i = 0; i < 16; i++)
{
angle = self->angle+i*(ANG45/16);
slope = P_AimLineAttack (self, angle, MELEERANGE, &linetarget, 0, ALF_CHECK3D);
if (linetarget)
slope = P_AimLineAttack (self, angle, MELEERANGE, &t, 0, ALF_CHECK3D);
if (t.linetarget)
{
P_DamageMobj (linetarget, self, self, damage, NAME_Ice);
P_DamageMobj (t.linetarget, self, self, damage, NAME_Ice, DMG_USEANGLE, t.SourceAngleToTarget());
conedone = true;
break;
}

View File

@ -97,17 +97,20 @@ bool AMageStaffFX2::SpecialBlastHandling (AActor *source, fixed_t strength)
//
//============================================================================
void MStaffSpawn (AActor *pmo, angle_t angle)
void MStaffSpawn (AActor *pmo, angle_t angle, AActor *alttarget)
{
AActor *mo;
AActor *linetarget;
FTranslatedLineTarget t;
mo = P_SpawnPlayerMissile (pmo, 0, 0, 8*FRACUNIT,
RUNTIME_CLASS(AMageStaffFX2), angle, &linetarget);
RUNTIME_CLASS(AMageStaffFX2), angle, &t);
if (mo)
{
mo->target = pmo;
mo->tracer = linetarget;
if (t.linetarget && !t.unlinked)
mo->tracer = t.linetarget;
else
mo->tracer = alttarget;
}
}
@ -123,7 +126,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MStaffAttack)
angle_t angle;
player_t *player;
AActor *linetarget;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
@ -139,18 +142,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_MStaffAttack)
angle = self->angle;
// [RH] Let's try and actually track what the player aimed at
P_AimLineAttack (self, angle, PLAYERMISSILERANGE, &linetarget, ANGLE_1*32);
if (linetarget == NULL)
P_AimLineAttack (self, angle, PLAYERMISSILERANGE, &t, ANGLE_1*32);
if (t.linetarget == NULL)
{
BlockCheckLine.x = self->X();
BlockCheckLine.y = self->Y();
BlockCheckLine.dx = -finesine[angle >> ANGLETOFINESHIFT];
BlockCheckLine.dy = -finecosine[angle >> ANGLETOFINESHIFT];
linetarget = P_BlockmapSearch (self, 10, FrontBlockCheck);
t.linetarget = P_BlockmapSearch (self, 10, FrontBlockCheck);
}
MStaffSpawn (self, angle);
MStaffSpawn (self, angle-ANGLE_1*5);
MStaffSpawn (self, angle+ANGLE_1*5);
MStaffSpawn (self, angle, t.linetarget);
MStaffSpawn (self, angle-ANGLE_1*5, t.linetarget);
MStaffSpawn (self, angle+ANGLE_1*5, t.linetarget);
S_Sound (self, CHAN_WEAPON, "MageStaffFire", 1, ATTN_NORM);
weapon->MStaffCount = 3;
return 0;

View File

@ -18,8 +18,6 @@ static FRandom pr_snoutattack ("SnoutAttack");
static FRandom pr_pigattack ("PigAttack");
static FRandom pr_pigplayerthink ("PigPlayerThink");
extern void AdjustPlayerAngle (AActor *, AActor *);
// Pig player ---------------------------------------------------------------
class APigPlayer : public APlayerPawn
@ -67,7 +65,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SnoutAttack)
int slope;
player_t *player;
AActor *puff;
AActor *linetarget;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
@ -76,12 +74,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_SnoutAttack)
damage = 3+(pr_snoutattack()&3);
angle = player->mo->angle;
slope = P_AimLineAttack(player->mo, angle, MELEERANGE, &linetarget);
puff = P_LineAttack(player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "SnoutPuff", true, &linetarget);
slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
puff = P_LineAttack(player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "SnoutPuff", true, &t);
S_Sound(player->mo, CHAN_VOICE, "PigActive", 1, ATTN_NORM);
if(linetarget)
if(t.linetarget)
{
AdjustPlayerAngle(player->mo, linetarget);
AdjustPlayerAngle(player->mo, &t);
if(puff != NULL)
{ // Bit something
S_Sound(player->mo, CHAN_VOICE, "PigAttack", 1, ATTN_NORM);

View File

@ -100,7 +100,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_JabDagger)
int damage;
int pitch;
int power;
AActor *linetarget;
FTranslatedLineTarget t;
power = MIN(10, self->player->mo->stamina / 10);
damage = (pr_jabdagger() % (power + 8)) * (power + 2);
@ -111,18 +111,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_JabDagger)
}
angle = self->angle + (pr_jabdagger.Random2() << 18);
pitch = P_AimLineAttack (self, angle, 80*FRACUNIT, &linetarget);
P_LineAttack (self, angle, 80*FRACUNIT, pitch, damage, NAME_Melee, "StrifeSpark", true, &linetarget);
pitch = P_AimLineAttack (self, angle, 80*FRACUNIT);
P_LineAttack (self, angle, 80*FRACUNIT, pitch, damage, NAME_Melee, "StrifeSpark", true, &t);
// turn to face target
if (linetarget)
if (t.linetarget)
{
S_Sound (self, CHAN_WEAPON,
linetarget->flags & MF_NOBLOOD ? "misc/metalhit" : "misc/meathit",
t.linetarget->flags & MF_NOBLOOD ? "misc/metalhit" : "misc/meathit",
1, ATTN_NORM);
self->angle = self->AngleTo(linetarget);
self->angle = t.SourceAngleToTarget();
self->flags |= MF_JUSTATTACKED;
P_DaggerAlert (self, linetarget);
P_DaggerAlert (self, t.linetarget);
}
else
{
@ -978,7 +978,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil1)
AActor *spot;
player_t *player = self->player;
AActor *linetarget;
FTranslatedLineTarget t;
if (player == NULL || player->ReadyWeapon == NULL)
return 0;
@ -986,13 +986,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil1)
P_DamageMobj (self, self, NULL, 1*4, 0, DMG_NO_ARMOR);
S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM);
P_BulletSlope (self, &linetarget);
if (linetarget != NULL)
P_BulletSlope (self, &t, ALF_PORTALRESTRICT);
if (t.linetarget != NULL)
{
spot = Spawn("SpectralLightningSpot", linetarget->X(), linetarget->Y(), linetarget->floorz, ALLOW_REPLACE);
spot = Spawn("SpectralLightningSpot", t.linetarget->X(), t.linetarget->Y(), t.linetarget->floorz, ALLOW_REPLACE);
if (spot != NULL)
{
spot->tracer = linetarget;
spot->tracer = t.linetarget;
}
}
else
@ -1080,7 +1080,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4)
AActor *spot;
player_t *player = self->player;
AActor *linetarget;
FTranslatedLineTarget t;
if (player == NULL || player->ReadyWeapon == NULL)
return 0;
@ -1088,13 +1088,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4)
P_DamageMobj (self, self, NULL, 4*4, 0, DMG_NO_ARMOR);
S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM);
P_BulletSlope (self, &linetarget);
if (linetarget != NULL)
P_BulletSlope (self, &t, ALF_PORTALRESTRICT);
if (t.linetarget != NULL)
{
spot = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindActor("SpectralLightningBigV1"), self->angle, &linetarget);
spot = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindActor("SpectralLightningBigV1"), self->angle, &t, NULL, false, false, ALF_PORTALRESTRICT);
if (spot != NULL)
{
spot->tracer = linetarget;
spot->tracer = t.linetarget;
}
}
else

View File

@ -4939,7 +4939,9 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
{
if (actor->player != NULL && actor->player->playerstate == PST_LIVE)
{
P_BulletSlope(actor, &actor);
FTranslatedLineTarget t;
P_BulletSlope(actor, &t, ALF_PORTALRESTRICT);
actor = t.linetarget;
}
else
{

View File

@ -425,16 +425,16 @@ bool AActor::SuggestMissileAttack (fixed_t dist)
bool P_HitFriend(AActor * self)
{
AActor *linetarget;
FTranslatedLineTarget t;
if (self->flags&MF_FRIENDLY && self->target != NULL)
{
angle_t angle = self->AngleTo(self->target);
fixed_t dist = self->AproxDistance (self->target);
P_AimLineAttack (self, angle, dist, &linetarget, 0, true);
if (linetarget != NULL && linetarget != self->target)
P_AimLineAttack (self, angle, dist, &t, 0, true);
if (t.linetarget != NULL && t.linetarget != self->target)
{
return self->IsFriend (linetarget);
return self->IsFriend (t.linetarget);
}
}
return false;
@ -2990,7 +2990,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail)
return 0;
fixed_t saved_pitch = self->pitch;
AActor *linetarget;
FTranslatedLineTarget t;
// [RH] Andy Baker's stealth monsters
if (self->flags & MF_STEALTH)
@ -3002,8 +3002,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail)
self->angle = self->AngleTo(self->target);
self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &linetarget, ANGLE_1*60, 0, self->target);
if (linetarget == NULL)
self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &t, ANGLE_1*60, 0, self->target);
if (t.linetarget == NULL)
{
// We probably won't hit the target, but aim at it anyway so we don't look stupid.
fixedvec2 pos = self->Vec2To(self->target);

View File

@ -927,7 +927,7 @@ static inline bool isFakePain(AActor *target, AActor *inflictor, int damage)
// Returns the amount of damage actually inflicted upon the target, or -1 if
// the damage was cancelled.
int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags)
int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags, angle_t angle)
{
unsigned ang;
player_t *player = NULL;
@ -1151,11 +1151,15 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
{
AActor *origin = (source && (flags & DMG_INFLICTOR_IS_PUFF))? source : inflictor;
// If the origin and target are in exactly the same spot, choose a random direction.
// (Most likely cause is from telefragging somebody during spawning because they
// haven't moved from their spawn spot at all.)
if (origin->X() == target->X() && origin->Y() == target->Y())
if (flags & DMG_USEANGLE)
{
ang = angle;
}
else if (origin->X() == target->X() && origin->Y() == target->Y())
{
// If the origin and target are in exactly the same spot, choose a random direction.
// (Most likely cause is from telefragging somebody during spawning because they
// haven't moved from their spawn spot at all.)
ang = pr_kickbackdir.GenRand32();
}
else

View File

@ -37,6 +37,7 @@ struct sector_t;
struct msecnode_t;
struct secplane_t;
struct FCheckPosition;
struct FTranslatedLineTarget;
#include <stdlib.h>
@ -173,7 +174,7 @@ AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, PClassAct
AActor *P_SpawnPlayerMissile (AActor* source, PClassActor *type);
AActor *P_SpawnPlayerMissile (AActor *source, PClassActor *type, angle_t angle);
AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, PClassActor *type, angle_t angle,
AActor **pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false, bool noautoaim = false);
FTranslatedLineTarget *pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false, bool noautoaim = false, int aimflags = 0);
void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheight=false);
@ -304,7 +305,7 @@ void P_FindFloorCeiling (AActor *actor, int flags=0);
bool P_ChangeSector (sector_t* sector, int crunch, int amt, int floorOrCeil, bool isreset);
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget = NULL, fixed_t vrange=0, int flags = 0, AActor *target=NULL, AActor *friender=NULL);
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, FTranslatedLineTarget *pLineTarget = NULL, fixed_t vrange=0, int flags = 0, AActor *target=NULL, AActor *friender=NULL);
enum // P_AimLineAttack flags
{
@ -313,6 +314,7 @@ enum // P_AimLineAttack flags
ALF_CHECKNONSHOOTABLE = 4,
ALF_CHECKCONVERSATION = 8,
ALF_NOFRIENDS = 16,
ALF_PORTALRESTRICT = 32, // only work through portals with a global offset (to be used for stuff that cannot remember the calculated FTranslatedLineTarget info)
};
enum // P_LineAttack flags
@ -322,11 +324,12 @@ enum // P_LineAttack flags
LAF_NOIMPACTDECAL = 4
};
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL);
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL);
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, PClassActor *pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL);
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, int flags = 0, FTranslatedLineTarget *victim = NULL, int *actualdamage = NULL);
void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch);
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, FTranslatedLineTarget *t, AActor *puff); // hitscan version
void P_TraceBleed (int damage, AActor *target); // random direction version
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, bool force = false);
@ -382,7 +385,7 @@ extern BYTE* rejectmatrix; // for fast sight rejection
// P_INTER
//
void P_TouchSpecialThing (AActor *special, AActor *toucher);
int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags=0);
int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags=0, angle_t angle = 0);
void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage, int duration, int period, FName type);
bool P_GiveBody (AActor *actor, int num, int max=0);
bool P_PoisonPlayer (player_t *player, AActor *poisoner, AActor *source, int poison);
@ -399,6 +402,7 @@ enum EDmgFlags
DMG_FOILINVUL = 64,
DMG_FOILBUDDHA = 128,
DMG_NO_PROTECT = 256,
DMG_USEANGLE = 512,
};

View File

@ -3787,7 +3787,7 @@ void aim_t::AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t en
//
//============================================================================
fixed_t P_AimLineAttack(AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange,
fixed_t P_AimLineAttack(AActor *t1, angle_t angle, fixed_t distance, FTranslatedLineTarget *pLineTarget, fixed_t vrange,
int flags, AActor *target, AActor *friender)
{
fixed_t x2;
@ -3881,7 +3881,18 @@ fixed_t P_AimLineAttack(AActor *t1, angle_t angle, fixed_t distance, AActor **pL
}
if (pLineTarget)
{
*pLineTarget = aim.linetarget;
if (aim.linetarget)
{
pLineTarget->linetarget = aim.linetarget;
pLineTarget->hitangle = angle;
pLineTarget->targetPosFromSrc = aim.linetarget->Pos();
pLineTarget->targetAngleFromSrc = aim.linetarget->angle;
pLineTarget->sourcePosFromTarget = t1->Pos();
pLineTarget->sourceAngleFromTarget = t1->angle;
pLineTarget->unlinked = false;
}
else
memset(pLineTarget, 0, sizeof(*pLineTarget));
}
return aim.linetarget ? aim.aimpitch : t1->pitch;
}
@ -3936,7 +3947,7 @@ static ETraceStatus CheckForActor(FTraceResults &res, void *userdata)
//==========================================================================
AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
int pitch, int damage, FName damageType, PClassActor *pufftype, int flags, AActor **victim, int *actualdamage)
int pitch, int damage, FName damageType, PClassActor *pufftype, int flags, FTranslatedLineTarget*victim, int *actualdamage)
{
fixed_t vx, vy, vz, shootz;
FTraceResults trace;
@ -3953,7 +3964,7 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
if (victim != NULL)
{
*victim = NULL;
memset(victim, 0, sizeof(*victim));
}
if (actualdamage != NULL)
{
@ -4136,6 +4147,7 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
puff = P_SpawnPuff(t1, pufftype, hitx, hity, hitz, angle - ANG180, 2, puffFlags | PF_HITTHING | PF_TEMPORARY);
killPuff = true;
}
#pragma message("damage angle")
newdam = P_DamageMobj(trace.Actor, puff ? puff : t1, t1, damage, damageType, dmgflags);
if (actualdamage != NULL)
{
@ -4175,7 +4187,13 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
}
if (victim != NULL)
{
*victim = trace.Actor;
victim->linetarget = trace.Actor;
victim->hitangle = angle;
victim->targetPosFromSrc = trace.Actor->Pos();
victim->targetAngleFromSrc = trace.Actor->angle;
victim->sourcePosFromTarget = t1->Pos();
victim->sourceAngleFromTarget = t1->angle;
victim->unlinked = false;
}
}
if (trace.Crossed3DWater || trace.CrossedWater)
@ -4198,22 +4216,22 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
}
AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
int pitch, int damage, FName damageType, FName pufftype, int flags, AActor **victim, int *actualdamage)
int pitch, int damage, FName damageType, FName pufftype, int flags, FTranslatedLineTarget *victim, int *actualdamage)
{
PClassActor *type = PClass::FindActor(pufftype);
if (victim != NULL)
{
*victim = NULL;
}
if (type == NULL)
{
if (victim != NULL)
{
memset(victim, 0, sizeof(*victim));
}
Printf("Attempt to spawn unknown actor type '%s'\n", pufftype.GetChars());
return NULL;
}
else
{
return P_LineAttack(t1, angle, distance, pitch, damage, damageType, type, flags, victim, actualdamage);
}
return NULL;
}
//==========================================================================
@ -4395,6 +4413,24 @@ void P_TraceBleed(int damage, AActor *target, AActor *missile)
//
//==========================================================================
void P_TraceBleed(int damage, FTranslatedLineTarget *t, AActor *puff)
{
if (t->linetarget == NULL || puff->flags3 & MF3_BLOODLESSIMPACT)
{
return;
}
fixed_t randpitch = (pr_tracebleed() - 128) << 16;
P_TraceBleed(damage, t->linetarget->X(), t->linetarget->Y(), t->linetarget->Z() + t->linetarget->height / 2,
t->linetarget, t->SourceAngleToTarget(), 0);
}
//==========================================================================
//
//
//
//==========================================================================
void P_TraceBleed(int damage, AActor *target)
{
if (target != NULL)
@ -4573,6 +4609,7 @@ void P_RailAttack(AActor *source, int damage, int offset_xy, fixed_t offset_z, i
if (puffDefaults->flags3 & MF3_FOILINVUL) dmgFlagPass |= DMG_FOILINVUL;
if (puffDefaults->flags7 & MF7_FOILBUDDHA) dmgFlagPass |= DMG_FOILBUDDHA;
}
#pragma message("damage angle")
int newdam = P_DamageMobj(hitactor, thepuff ? thepuff : source, source, damage, damagetype, dmgFlagPass);
if (bleed)
@ -4690,38 +4727,26 @@ void P_AimCamera(AActor *t1, fixed_t &CameraX, fixed_t &CameraY, fixed_t &Camera
bool P_TalkFacing(AActor *player)
{
AActor *linetarget;
static const int angleofs[] = { 0, ANGLE_90 >> 4, - ANGLE_90 >> 4 };
FTranslatedLineTarget t;
P_AimLineAttack(player, player->angle, TALKRANGE, &linetarget, ANGLE_1 * 35, ALF_FORCENOSMART | ALF_CHECKCONVERSATION);
if (linetarget == NULL)
for (int angle : angleofs)
{
P_AimLineAttack(player, player->angle + (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1 * 35, ALF_FORCENOSMART | ALF_CHECKCONVERSATION);
if (linetarget == NULL)
P_AimLineAttack(player, player->angle + angle, TALKRANGE, &t, ANGLE_1 * 35, ALF_FORCENOSMART | ALF_CHECKCONVERSATION | ALF_PORTALRESTRICT);
if (t.linetarget != NULL)
{
P_AimLineAttack(player, player->angle - (ANGLE_90 >> 4), TALKRANGE, &linetarget, ANGLE_1 * 35, ALF_FORCENOSMART | ALF_CHECKCONVERSATION);
if (linetarget == NULL)
if (t.linetarget->health > 0 && // Dead things can't talk.
t.linetarget->flags4 & MF4_INCOMBAT && // Fighting things don't talk either.
t.linetarget->Conversation != NULL)
{
return false;
// Give the NPC a chance to play a brief animation
t.linetarget->ConversationAnimation(0);
P_StartConversation(t.linetarget, player, true, true);
return true;
}
return false;
}
}
// Dead things can't talk.
if (linetarget->health <= 0)
{
return false;
}
// Fighting things don't talk either.
if (linetarget->flags4 & MF4_INCOMBAT)
{
return false;
}
if (linetarget->Conversation != NULL)
{
// Give the NPC a chance to play a brief animation
linetarget->ConversationAnimation(0);
P_StartConversation(linetarget, player, true, true);
return true;
}
return false;
}

View File

@ -6164,13 +6164,13 @@ AActor *P_SpawnPlayerMissile (AActor *source, PClassActor *type, angle_t angle)
}
AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
PClassActor *type, angle_t angle, AActor **pLineTarget, AActor **pMissileActor,
bool nofreeaim, bool noautoaim)
PClassActor *type, angle_t angle, FTranslatedLineTarget *pLineTarget, AActor **pMissileActor,
bool nofreeaim, bool noautoaim, int aimflags)
{
static const int angdiff[3] = { -(1<<26), 1<<26, 0 };
angle_t an = angle;
angle_t pitch;
AActor *linetarget;
FTranslatedLineTarget scratch;
AActor *defaultobject = GetDefaultByType(type);
int vrange = nofreeaim ? ANGLE_1*35 : 0;
@ -6178,12 +6178,13 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
{
return NULL;
}
if (!pLineTarget) pLineTarget = &scratch;
if (source->player && source->player->ReadyWeapon && ((source->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM) || noautoaim))
{
// Keep exactly the same angle and pitch as the player's own aim
an = angle;
pitch = source->pitch;
linetarget = NULL;
pLineTarget->linetarget = NULL;
}
else // see which target is to be aimed at
{
@ -6196,7 +6197,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
do
{
an = angle + angdiff[i];
pitch = P_AimLineAttack (source, an, linetargetrange, &linetarget, vrange);
pitch = P_AimLineAttack (source, an, linetargetrange, pLineTarget, vrange, aimflags);
if (source->player != NULL &&
!nofreeaim &&
@ -6205,9 +6206,9 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
{
break;
}
} while (linetarget == NULL && --i >= 0);
} while (pLineTarget->linetarget == NULL && --i >= 0);
if (linetarget == NULL)
if (pLineTarget->linetarget == NULL)
{
an = angle;
if (nofreeaim || !level.IsFreelookAllowed())
@ -6216,7 +6217,6 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
}
}
}
if (pLineTarget) *pLineTarget = linetarget;
if (z != ONFLOORZ && z != ONCEILINGZ)
{

View File

@ -919,20 +919,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AInventory, A_GunFlash)
// the height of the intended target
//
angle_t P_BulletSlope (AActor *mo, AActor **pLineTarget)
angle_t P_BulletSlope (AActor *mo, FTranslatedLineTarget *pLineTarget, int aimflags)
{
static const int angdiff[3] = { -(1<<26), 1<<26, 0 };
int i;
angle_t an;
angle_t pitch;
AActor *linetarget;
FTranslatedLineTarget scratch;
if (pLineTarget == NULL) pLineTarget = &scratch;
// see which target is to be aimed at
i = 2;
do
{
an = mo->angle + angdiff[i];
pitch = P_AimLineAttack (mo, an, 16*64*FRACUNIT, &linetarget);
pitch = P_AimLineAttack (mo, an, 16*64*FRACUNIT, pLineTarget, 0, aimflags);
if (mo->player != NULL &&
level.IsFreelookAllowed() &&
@ -940,11 +941,8 @@ angle_t P_BulletSlope (AActor *mo, AActor **pLineTarget)
{
break;
}
} while (linetarget == NULL && --i >= 0);
if (pLineTarget != NULL)
{
*pLineTarget = linetarget;
}
} while (pLineTarget->linetarget == NULL && --i >= 0);
return pitch;
}

View File

@ -88,7 +88,7 @@ void P_BringUpWeapon (player_t *player);
void P_FireWeapon (player_t *player);
void P_DropWeapon (player_t *player);
void P_BobWeapon (player_t *player, pspdef_t *psp, fixed_t *x, fixed_t *y);
angle_t P_BulletSlope (AActor *mo, AActor **pLineTarget = NULL);
angle_t P_BulletSlope (AActor *mo, FTranslatedLineTarget *pLineTarget = NULL, int aimflags = 0);
void P_GunShot (AActor *mo, bool accurate, PClassActor *pufftype, angle_t pitch);
void DoReadyWeapon(AActor *self);

View File

@ -960,7 +960,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfCloser)
else
{
// Does the player aim at something that can be shot?
P_BulletSlope(self, &target);
FTranslatedLineTarget t;
P_BulletSlope(self, &t, ALF_PORTALRESTRICT);
target = t.linetarget;
}
return DoJumpIfCloser(target, VM_ARGS_NAMES);
}
@ -1637,7 +1639,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile)
player_t *player = self->player;
AWeapon *weapon = player->ReadyWeapon;
AActor *linetarget;
FTranslatedLineTarget t;
// Only use ammo if called from a weapon
if (useammo && ACTION_CALL_FROM_WEAPON() && weapon)
@ -1659,7 +1661,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile)
// Temporarily adjusts the pitch
fixed_t saved_player_pitch = self->pitch;
self->pitch -= pitch;
AActor * misl=P_SpawnPlayerMissile (self, x, y, z, ti, shootangle, &linetarget, NULL, false, (flags & FPF_NOAUTOAIM) != 0);
AActor * misl=P_SpawnPlayerMissile (self, x, y, z, ti, shootangle, &t, NULL, false, (flags & FPF_NOAUTOAIM) != 0);
self->pitch = saved_player_pitch;
// automatic handling of seeker missiles
@ -1667,8 +1669,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FireCustomMissile)
{
if (flags & FPF_TRANSFERTRANSLATION)
misl->Translation = self->Translation;
if (linetarget && (misl->flags2 & MF2_SEEKERMISSILE))
misl->tracer = linetarget;
if (t.linetarget && !t.unlinked && (misl->flags2 & MF2_SEEKERMISSILE))
misl->tracer = t.linetarget;
if (!(flags & FPF_AIMATANGLE))
{
// This original implementation is to aim straight ahead and then offset
@ -1727,7 +1729,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
angle_t angle;
int pitch;
AActor * linetarget;
FTranslatedLineTarget t;
int actualdamage;
if (!norandom)
@ -1736,10 +1738,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
angle = self->angle + (pr_cwpunch.Random2() << 18);
if (range == 0)
range = MELEERANGE;
pitch = P_AimLineAttack (self, angle, range, &linetarget);
pitch = P_AimLineAttack (self, angle, range, &t);
// only use ammo when actually hitting something!
if ((flags & CPF_USEAMMO) && linetarget && weapon && ACTION_CALL_FROM_WEAPON())
if ((flags & CPF_USEAMMO) && t.linetarget && weapon && ACTION_CALL_FROM_WEAPON())
{
if (!weapon->DepleteAmmo(weapon->bAltFire, true))
return 0; // out of ammo
@ -1749,15 +1751,15 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
pufftype = PClass::FindActor(NAME_BulletPuff);
int puffFlags = LAF_ISMELEEATTACK | ((flags & CPF_NORANDOMPUFFZ) ? LAF_NORANDOMPUFFZ : 0);
P_LineAttack (self, angle, range, pitch, damage, NAME_Melee, pufftype, puffFlags, &linetarget, &actualdamage);
P_LineAttack (self, angle, range, pitch, damage, NAME_Melee, pufftype, puffFlags, &t, &actualdamage);
if (!linetarget)
if (!t.linetarget)
{
if (MissSound) S_Sound(self, CHAN_WEAPON, MissSound, 1, ATTN_NORM);
}
else
{
if (lifesteal && !(linetarget->flags5 & MF5_DONTDRAIN))
if (lifesteal && !(t.linetarget->flags5 & MF5_DONTDRAIN))
{
if (flags & CPF_STEALARMOR)
{
@ -1794,11 +1796,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
if (!(flags & CPF_NOTURN))
{
// turn to face target
self->angle = self->AngleTo(linetarget);
self->angle = t.SourceAngleToTarget();
}
if (flags & CPF_PULLIN) self->flags |= MF_JUSTATTACKED;
if (flags & CPF_DAGGER) P_DaggerAlert (self, linetarget);
if (flags & CPF_DAGGER) P_DaggerAlert (self, t.linetarget);
}
return 0;
}
@ -1900,7 +1902,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
if (range == 0) range = 8192*FRACUNIT;
if (sparsity == 0) sparsity = 1;
AActor *linetarget;
FTranslatedLineTarget t;
fixedvec3 savedpos = self->Pos();
angle_t saved_angle = self->angle;
@ -1923,8 +1925,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomRailgun)
{
self->angle = self->AngleTo(self->target);
}
self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &linetarget, ANGLE_1*60, 0, aim ? self->target : NULL);
if (linetarget == NULL && aim)
self->pitch = P_AimLineAttack (self, self->angle, MISSILERANGE, &t, ANGLE_1*60, 0, aim ? self->target : NULL);
if (t.linetarget == NULL && aim)
{
// We probably won't hit the target, but aim at it anyway so we don't look stupid.
fixedvec2 pos = self->Vec2To(self->target);
@ -3929,6 +3931,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
angle_t an;
AActor *target, *viewport;
FTranslatedLineTarget t;
bool doCheckSight;
@ -3964,12 +3967,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
else
{
// Does the player aim at something that can be shot?
P_AimLineAttack(self, self->angle, MISSILERANGE, &target, (flags & JLOSF_NOAUTOAIM) ? ANGLE_1/2 : 0);
P_AimLineAttack(self, self->angle, MISSILERANGE, &t, (flags & JLOSF_NOAUTOAIM) ? ANGLE_1/2 : 0, ALF_PORTALRESTRICT);
if (!target)
if (!t.linetarget)
{
ACTION_RETURN_STATE(NULL);
}
target = t.linetarget;
switch (flags & (JLOSF_TARGETLOS|JLOSF_FLIPFOV))
{