mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-13 07:57:58 +00:00
Merge branch 'zmaster'
This commit is contained in:
commit
6f28735b45
21 changed files with 661 additions and 431 deletions
15
src/actor.h
15
src/actor.h
|
@ -1409,21 +1409,8 @@ AActor *P_LinePickActor(AActor *t1, angle_t angle, fixed_t distance, int pitch,
|
|||
struct FTranslatedLineTarget
|
||||
{
|
||||
AActor *linetarget;
|
||||
angle_t hitangle;
|
||||
fixedvec3 targetPosFromSrc;
|
||||
angle_t targetAngleFromSrc;
|
||||
fixedvec3 sourcePosFromTarget;
|
||||
angle_t sourceAngleFromTarget;
|
||||
angle_t angleFromSource;
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Punch)
|
|||
if (t.linetarget)
|
||||
{
|
||||
S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
|
||||
self->angle = t.SourceAngleToTarget();
|
||||
self->angle = t.angleFromSource;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw)
|
|||
// turn to face target
|
||||
if (!(flags & SF_NOTURN))
|
||||
{
|
||||
angle = t.SourceAngleToTarget();
|
||||
angle = t.angleFromSource;
|
||||
if (angle - self->angle > ANG180)
|
||||
{
|
||||
if (angle - self->angle < (angle_t)(-ANG90 / 20))
|
||||
|
@ -696,7 +696,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
|
|||
damage = defdamage;
|
||||
}
|
||||
|
||||
int newdam = P_DamageMobj(t.linetarget, self->target, self->target, damage, dmgType, dmgFlags|DMG_USEANGLE, t.SourceAngleToTarget());
|
||||
int newdam = P_DamageMobj(t.linetarget, self->target, self->target, damage, dmgType, dmgFlags|DMG_USEANGLE, t.angleFromSource);
|
||||
P_TraceBleed(newdam > 0 ? newdam : damage, &t, self);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = t.SourceAngleToTarget();
|
||||
angle = t.angleFromSource;
|
||||
if (angle - self->angle > ANG180)
|
||||
{
|
||||
if (angle - self->angle < (angle_t)(-ANG90/20))
|
||||
|
@ -344,7 +344,7 @@ static void MarinePunch(AActor *self, int damagemul)
|
|||
if (t.linetarget)
|
||||
{
|
||||
S_Sound (self, CHAN_WEAPON, "*fist", 1, ATTN_NORM);
|
||||
self->angle = t.SourceAngleToTarget();
|
||||
self->angle = t.angleFromSource;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL1)
|
|||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &t);
|
||||
if (t.linetarget)
|
||||
{
|
||||
player->mo->angle = t.SourceAngleToTarget();
|
||||
player->mo->angle = t.angleFromSource;
|
||||
}
|
||||
P_PlayPeck (player->mo);
|
||||
player->chickenPeck = 12;
|
||||
|
@ -224,7 +224,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BeakAttackPL2)
|
|||
P_LineAttack (player->mo, angle, MELEERANGE, slope, damage, NAME_Melee, "BeakPuff", true, &t);
|
||||
if (t.linetarget)
|
||||
{
|
||||
player->mo->angle = t.SourceAngleToTarget();
|
||||
player->mo->angle = t.angleFromSource;
|
||||
}
|
||||
P_PlayPeck (player->mo);
|
||||
player->chickenPeck = 12;
|
||||
|
|
|
@ -94,7 +94,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_StaffAttack)
|
|||
{
|
||||
//S_StartSound(player->mo, sfx_stfhit);
|
||||
// turn to face target
|
||||
self->angle = t.SourceAngleToTarget();
|
||||
self->angle = t.angleFromSource;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -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 = t.SourceAngleToTarget();
|
||||
angle = t.angleFromSource;
|
||||
if (angle-self->angle > ANG180)
|
||||
{
|
||||
if ((int)(angle-self->angle) < -ANG90/20)
|
||||
|
@ -675,7 +675,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
|
|||
if (t.linetarget && self->target != t.linetarget)
|
||||
{
|
||||
self->tracer = t.linetarget;
|
||||
angle = t.SourceAngleToTarget();
|
||||
angle = t.angleFromSource;
|
||||
newAngle = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
|
|||
P_LineAttack(pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, puff, false, &t);
|
||||
if (t.linetarget != NULL)
|
||||
{
|
||||
pmo->angle = t.SourceAngleToTarget();
|
||||
pmo->angle = t.angleFromSource;
|
||||
if (((t.linetarget->player && (!t.linetarget->IsTeammate(pmo) || level.teamdamage != 0)) || t.linetarget->flags3&MF3_ISMONSTER)
|
||||
&& (!(t.linetarget->flags2&(MF2_DORMANT | MF2_INVULNERABLE))))
|
||||
{
|
||||
|
|
|
@ -245,7 +245,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FAxeAttack)
|
|||
{
|
||||
if (t.linetarget->flags3&MF3_ISMONSTER || t.linetarget->player)
|
||||
{
|
||||
P_ThrustMobj(t.linetarget, t.hitangle, power);
|
||||
P_ThrustMobj(t.linetarget, t.angleFromSource, power);
|
||||
}
|
||||
AdjustPlayerAngle(pmo, &t);
|
||||
useMana++;
|
||||
|
|
|
@ -57,7 +57,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack)
|
|||
AdjustPlayerAngle(pmo, &t);
|
||||
if (t.linetarget->flags3 & MF3_ISMONSTER || t.linetarget->player)
|
||||
{
|
||||
P_ThrustMobj(t.linetarget, t.hitangle, power);
|
||||
P_ThrustMobj(t.linetarget, t.angleFromSource, power);
|
||||
}
|
||||
pmo->weaponspecial = false; // Don't throw a hammer
|
||||
goto hammerdone;
|
||||
|
@ -73,7 +73,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FHammerAttack)
|
|||
AdjustPlayerAngle(pmo, &t);
|
||||
if (t.linetarget->flags3 & MF3_ISMONSTER || t.linetarget->player)
|
||||
{
|
||||
P_ThrustMobj(t.linetarget, t.hitangle, power);
|
||||
P_ThrustMobj(t.linetarget, t.angleFromSource, power);
|
||||
}
|
||||
pmo->weaponspecial = false; // Don't throw a hammer
|
||||
goto hammerdone;
|
||||
|
|
|
@ -30,7 +30,7 @@ void AdjustPlayerAngle (AActor *pmo, FTranslatedLineTarget *t)
|
|||
angle_t angle;
|
||||
int difference;
|
||||
|
||||
angle = t->SourceAngleToTarget();
|
||||
angle = t->angleFromSource;
|
||||
difference = (int)angle - (int)pmo->angle;
|
||||
if (abs(difference) > MAX_ANGLE_ADJUST)
|
||||
{
|
||||
|
@ -82,7 +82,7 @@ static bool TryPunch(APlayerPawn *pmo, angle_t angle, int damage, fixed_t power)
|
|||
if (t.linetarget->player != NULL ||
|
||||
(t.linetarget->Mass != INT_MAX && (t.linetarget->flags3 & MF3_ISMONSTER)))
|
||||
{
|
||||
P_ThrustMobj (t.linetarget, t.hitangle, power);
|
||||
P_ThrustMobj (t.linetarget, t.angleFromSource, power);
|
||||
}
|
||||
AdjustPlayerAngle (pmo, &t);
|
||||
return true;
|
||||
|
|
|
@ -82,7 +82,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireConePL1)
|
|||
slope = P_AimLineAttack (self, angle, MELEERANGE, &t, 0, ALF_CHECK3D);
|
||||
if (t.linetarget)
|
||||
{
|
||||
P_DamageMobj (t.linetarget, self, self, damage, NAME_Ice, DMG_USEANGLE, t.SourceAngleToTarget());
|
||||
P_DamageMobj (t.linetarget, self, self, damage, NAME_Ice, DMG_USEANGLE, t.angleFromSource);
|
||||
conedone = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_JabDagger)
|
|||
S_Sound (self, CHAN_WEAPON,
|
||||
t.linetarget->flags & MF_NOBLOOD ? "misc/metalhit" : "misc/meathit",
|
||||
1, ATTN_NORM);
|
||||
self->angle = t.SourceAngleToTarget();
|
||||
self->angle = t.angleFromSource;
|
||||
self->flags |= MF_JUSTATTACKED;
|
||||
P_DaggerAlert (self, t.linetarget);
|
||||
}
|
||||
|
|
|
@ -691,3 +691,4 @@ xx(Max_10_Exp)
|
|||
xx(__decorate_internal_int__)
|
||||
xx(__decorate_internal_bool__)
|
||||
xx(__decorate_internal_state__)
|
||||
xx(__decorate_internal_float__)
|
||||
|
|
|
@ -300,6 +300,7 @@ enum
|
|||
FFCF_NOFLOOR = 32,
|
||||
FFCF_NOCEILING = 64,
|
||||
FFCF_RESTRICTEDPORTAL = 128, // current values in the iterator's return are through a restricted portal type (i.e. some features are blocked.)
|
||||
FFCF_NODROPOFF = 256, // Caller does not need a dropoff (saves some time when checking portals)
|
||||
};
|
||||
void P_FindFloorCeiling (AActor *actor, int flags=0);
|
||||
|
||||
|
|
448
src/p_map.cpp
448
src/p_map.cpp
|
@ -2837,8 +2837,7 @@ void FSlide::SlideTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t
|
|||
}
|
||||
|
||||
// set openrange, opentop, openbottom
|
||||
P_LineOpening(open, slidemo, li, it.Trace().x + FixedMul(it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul(it.Trace().dy, in->frac));
|
||||
P_LineOpening(open, slidemo, li, it.InterceptPoint(in));
|
||||
|
||||
if (open.range < slidemo->height)
|
||||
goto isblocking; // doesn't fit
|
||||
|
@ -3192,8 +3191,7 @@ bool FSlide::BounceTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_
|
|||
}
|
||||
|
||||
|
||||
P_LineOpening(open, slidemo, li, it.Trace().x + FixedMul(it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul(it.Trace().dy, in->frac)); // set openrange, opentop, openbottom
|
||||
P_LineOpening(open, slidemo, li, it.InterceptPoint(in)); // set openrange, opentop, openbottom
|
||||
if (open.range < slidemo->height)
|
||||
goto bounceblocking; // doesn't fit
|
||||
|
||||
|
@ -3440,49 +3438,142 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
struct AimTarget : public FTranslatedLineTarget
|
||||
{
|
||||
angle_t pitch;
|
||||
fixed_t frac;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
frac = FIXED_MAX;
|
||||
}
|
||||
};
|
||||
|
||||
struct aim_t
|
||||
{
|
||||
enum
|
||||
{
|
||||
aim_up = 1,
|
||||
aim_down = 2
|
||||
};
|
||||
|
||||
fixed_t aimpitch;
|
||||
fixed_t attackrange;
|
||||
fixed_t shootz; // Height if not aiming up or down
|
||||
fixed_t limitz; // height limit for portals to avoid bad setups
|
||||
AActor* shootthing;
|
||||
AActor* friender; // actor to check friendliness again
|
||||
AActor* aimtarget; // if we want to aim at precisely this target.
|
||||
|
||||
fixed_t toppitch, bottompitch;
|
||||
AActor * linetarget;
|
||||
AActor * thing_friend, *thing_other;
|
||||
angle_t pitch_friend, pitch_other;
|
||||
AimTarget linetarget;
|
||||
AimTarget thing_friend, thing_other;
|
||||
|
||||
int flags;
|
||||
sector_t * lastsector;
|
||||
secplane_t * lastfloorplane;
|
||||
secplane_t * lastceilingplane;
|
||||
|
||||
int aimdir;
|
||||
fixedvec3 startpos;
|
||||
fixedvec2 aimtrace;
|
||||
fixed_t startfrac;
|
||||
|
||||
bool crossedffloors;
|
||||
bool unlinked;
|
||||
|
||||
bool AimTraverse3DFloors(const divline_t &trace, intercept_t * in);
|
||||
// Creates a clone of this structure with the basic info copied.
|
||||
aim_t Clone()
|
||||
{
|
||||
aim_t cloned;
|
||||
|
||||
void AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, AActor *target = NULL);
|
||||
cloned.aimtrace = aimtrace;
|
||||
cloned.aimpitch = aimpitch;
|
||||
cloned.aimtarget = aimtarget;
|
||||
cloned.attackrange = attackrange;
|
||||
cloned.shootthing = shootthing;
|
||||
cloned.friender = friender;
|
||||
cloned.shootz = shootz;
|
||||
cloned.unlinked = unlinked;
|
||||
cloned.flags = flags;
|
||||
return cloned;
|
||||
}
|
||||
|
||||
};
|
||||
// Crosing a line portal does not require a recursive call. We can just alter the current set of data
|
||||
void CrossLinePortal(line_t *line)
|
||||
{
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// AimTraverse3DFloors
|
||||
//
|
||||
//============================================================================
|
||||
bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in)
|
||||
{
|
||||
//============================================================================
|
||||
//
|
||||
// SetResult
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void SetResult(AimTarget &res, fixed_t frac, AActor *th, fixed_t pitch)
|
||||
{
|
||||
if (res.frac > frac)
|
||||
{
|
||||
res.linetarget = th;
|
||||
res.pitch = pitch;
|
||||
res.angleFromSource = R_PointToAngle2(startpos.x, startpos.y, th->X(), th->Y());
|
||||
res.unlinked = unlinked;
|
||||
res.frac = frac;
|
||||
}
|
||||
}
|
||||
|
||||
void SetResult(AimTarget &res, AimTarget &set)
|
||||
{
|
||||
if (res.frac > set.frac)
|
||||
{
|
||||
res = set;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Result
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
AimTarget *Result()
|
||||
{
|
||||
AimTarget *result = &linetarget;
|
||||
if (result->linetarget == NULL)
|
||||
{
|
||||
if (thing_other.linetarget != NULL)
|
||||
{
|
||||
result = &thing_other;
|
||||
}
|
||||
else if (thing_friend.linetarget != NULL)
|
||||
{
|
||||
result = &thing_friend;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// AimTraverse3DFloors
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
bool AimTraverse3DFloors(const divline_t &trace, intercept_t * in, int frontflag, int *planestocheck)
|
||||
{
|
||||
sector_t * nextsector;
|
||||
secplane_t * nexttopplane, *nextbottomplane;
|
||||
line_t * li = in->d.line;
|
||||
|
||||
nextsector = NULL;
|
||||
nexttopplane = nextbottomplane = NULL;
|
||||
*planestocheck = aimdir;
|
||||
|
||||
if (li->backsector == NULL) return true; // shouldn't really happen but crashed once for me...
|
||||
if (li->frontsector->e->XFloor.ffloors.Size() || li->backsector->e->XFloor.ffloors.Size())
|
||||
{
|
||||
int frontflag;
|
||||
F3DFloor* rover;
|
||||
int highpitch, lowpitch;
|
||||
|
||||
|
@ -3490,15 +3581,13 @@ bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in)
|
|||
fixed_t trY = trace.y + FixedMul(trace.dy, in->frac);
|
||||
fixed_t dist = FixedMul(attackrange, in->frac);
|
||||
|
||||
frontflag = P_PointOnLineSide(shootthing->X(), shootthing->Y(), li);
|
||||
|
||||
// 3D floor check. This is not 100% accurate but normally sufficient when
|
||||
// combined with a final sight check
|
||||
for (int i = 1; i <= 2; i++)
|
||||
{
|
||||
sector_t * s = i == 1 ? li->frontsector : li->backsector;
|
||||
|
||||
for (unsigned k = 0; k<s->e->XFloor.ffloors.Size(); k++)
|
||||
for (unsigned k = 0; k < s->e->XFloor.ffloors.Size(); k++)
|
||||
{
|
||||
crossedffloors = true;
|
||||
rover = s->e->XFloor.ffloors[k];
|
||||
|
@ -3517,12 +3606,13 @@ bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in)
|
|||
// blocks completely
|
||||
if (lowpitch >= bottompitch) return false;
|
||||
// blocks upper edge of view
|
||||
if (lowpitch>toppitch)
|
||||
if (lowpitch > toppitch)
|
||||
{
|
||||
toppitch = lowpitch;
|
||||
if (frontflag != i - 1)
|
||||
{
|
||||
nexttopplane = rover->bottom.plane;
|
||||
*planestocheck &= ~aim_up;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3535,6 +3625,7 @@ bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in)
|
|||
if (frontflag != i - 1)
|
||||
{
|
||||
nextbottomplane = rover->top.plane;
|
||||
*planestocheck &= ~aim_down;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3565,20 +3656,127 @@ bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in)
|
|||
lastceilingplane = nexttopplane;
|
||||
lastfloorplane = nextbottomplane;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// PTR_AimTraverse
|
||||
// Sets linetaget and aimpitch when a target is aimed at.
|
||||
//
|
||||
//============================================================================
|
||||
//============================================================================
|
||||
//
|
||||
// traverses a sector portal
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void aim_t::AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, AActor *target)
|
||||
{
|
||||
FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES | PT_ADDTHINGS | PT_COMPATIBLE);
|
||||
void EnterSectorPortal(int position, fixed_t frac, sector_t *entersec, fixed_t newtoppitch, fixed_t newbottompitch)
|
||||
{
|
||||
AActor *portal = entersec->SkyBoxes[position];
|
||||
if (portal == NULL)
|
||||
if (position == sector_t::ceiling && portal->threshold < limitz) return;
|
||||
else if (position == sector_t::floor && portal->threshold > limitz) return;
|
||||
aim_t newtrace = Clone();
|
||||
|
||||
|
||||
newtrace.toppitch = newtoppitch;
|
||||
newtrace.bottompitch = newbottompitch;
|
||||
newtrace.aimdir = position == sector_t::ceiling? aim_t::aim_up : aim_t::aim_down;
|
||||
newtrace.startpos = { startpos.x + portal->scaleX, startpos.y + portal->scaleY, startpos.z };
|
||||
newtrace.startfrac = frac + FixedDiv(FRACUNIT, attackrange); // this is to skip the transition line to the portal which would produce a bogus opening
|
||||
newtrace.lastsector = P_PointInSector(newtrace.startpos.x + FixedMul(aimtrace.x, newtrace.startfrac) , newtrace.startpos.y + FixedMul(aimtrace.y, newtrace.startfrac));
|
||||
newtrace.limitz = portal->threshold;
|
||||
Printf("-----Entering %s portal from sector %d to sector %d\n", position ? "ceiling" : "floor", lastsector->sectornum, newtrace.lastsector->sectornum);
|
||||
newtrace.AimTraverse();
|
||||
SetResult(linetarget, newtrace.linetarget);
|
||||
SetResult(thing_friend, newtrace.thing_friend);
|
||||
SetResult(thing_other, newtrace.thing_other);
|
||||
Printf("-----Exiting %s portal\n", position ? "ceiling" : "floor");
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// traverses a line portal
|
||||
// simply calling PortalRelocate does not work here because more needs to be set up
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void EnterLinePortal(line_t *li, fixed_t frac)
|
||||
{
|
||||
aim_t newtrace = Clone();
|
||||
|
||||
FLinePortal *port = li->getPortal();
|
||||
line_t *dest = port->mDestination;
|
||||
|
||||
newtrace.toppitch = toppitch;
|
||||
newtrace.bottompitch = bottompitch;
|
||||
newtrace.aimdir = aimdir;
|
||||
newtrace.unlinked = (port->mType != PORTT_LINKED);
|
||||
newtrace.startpos = startpos;
|
||||
newtrace.aimtrace = aimtrace;
|
||||
P_TranslatePortalXY(li, dest, newtrace.startpos.x, newtrace.startpos.y);
|
||||
P_TranslatePortalZ(li, dest, newtrace.startpos.z);
|
||||
P_TranslatePortalVXVY(li, dest, newtrace.aimtrace.x, newtrace.aimtrace.y);
|
||||
|
||||
newtrace.startfrac = frac + FixedDiv(FRACUNIT, attackrange); // this is to skip the transition line to the portal which would produce a bogus opening
|
||||
|
||||
fixed_t x = newtrace.startpos.x + FixedMul(newtrace.aimtrace.x, newtrace.startfrac);
|
||||
fixed_t y = newtrace.startpos.y + FixedMul(newtrace.aimtrace.y, newtrace.startfrac);
|
||||
|
||||
newtrace.lastsector = P_PointInSector(x, y);
|
||||
P_TranslatePortalZ(li, dest, limitz);
|
||||
Printf("-----Entering line portal from sector %d to sector %d\n", lastsector->sectornum, newtrace.lastsector->sectornum);
|
||||
newtrace.AimTraverse();
|
||||
SetResult(linetarget, newtrace.linetarget);
|
||||
SetResult(thing_friend, newtrace.thing_friend);
|
||||
SetResult(thing_other, newtrace.thing_other);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// PTR_AimTraverse
|
||||
// Sets linetaget and aimpitch when a target is aimed at.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void AimTraverse()
|
||||
{
|
||||
// for smart aiming
|
||||
linetarget.Clear();
|
||||
thing_friend.Clear();
|
||||
thing_other.Clear();
|
||||
crossedffloors = lastsector->e->XFloor.ffloors.Size() != 0;
|
||||
lastfloorplane = lastceilingplane = NULL;
|
||||
|
||||
// check the initial sector for 3D-floors and portals
|
||||
bool ceilingportalstate = (aimdir & aim_t::aim_up) && toppitch < 0 && !lastsector->PortalBlocksMovement(sector_t::ceiling);
|
||||
bool floorportalstate = (aimdir & aim_t::aim_down) && bottompitch > 0 && !lastsector->PortalBlocksMovement(sector_t::floor);
|
||||
|
||||
for (auto rover : lastsector->e->XFloor.ffloors)
|
||||
{
|
||||
if ((rover->flags & FF_SHOOTTHROUGH) || !(rover->flags & FF_EXISTS)) continue;
|
||||
|
||||
fixed_t bottomz = rover->bottom.plane->ZatPoint(startpos);
|
||||
|
||||
if (bottomz >= startpos.z + shootthing->height)
|
||||
{
|
||||
lastceilingplane = rover->bottom.plane;
|
||||
// no ceiling portal if below a 3D floor
|
||||
ceilingportalstate = false;
|
||||
}
|
||||
|
||||
bottomz = rover->top.plane->ZatPoint(startpos);
|
||||
if (bottomz <= startpos.z)
|
||||
{
|
||||
lastfloorplane = rover->top.plane;
|
||||
// no floor portal if above a 3D floor
|
||||
floorportalstate = false;
|
||||
}
|
||||
}
|
||||
if (ceilingportalstate) EnterSectorPortal(sector_t::ceiling, 0, lastsector, toppitch, MIN(0, bottompitch));
|
||||
if (floorportalstate) EnterSectorPortal(sector_t::floor, 0, lastsector, MAX(0, toppitch), bottompitch);
|
||||
|
||||
FPathTraverse it(startpos.x, startpos.y, aimtrace.x, aimtrace.y, PT_ADDLINES | PT_ADDTHINGS | PT_COMPATIBLE | PT_DELTA, startfrac);
|
||||
intercept_t *in;
|
||||
|
||||
Printf("Start AimTraverse, start = %f,%f,%f, vect = %f,%f,%f\n",
|
||||
startpos.x / 65536., startpos.y / 65536., startpos.y / 65536.,
|
||||
aimtrace.x / 65536., aimtrace.y / 65536.);
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
line_t* li;
|
||||
|
@ -3589,9 +3787,21 @@ void aim_t::AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t en
|
|||
fixed_t dist;
|
||||
int thingpitch;
|
||||
|
||||
if (linetarget.linetarget != NULL && in->frac > linetarget.frac) return; // we already found something better in another portal section.
|
||||
|
||||
if (in->isaline)
|
||||
{
|
||||
li = in->d.line;
|
||||
int frontflag = P_PointOnLineSidePrecise(startpos.x, startpos.y, li);
|
||||
|
||||
Printf("Found line %d: toppitch = %f, bottompitch = %f\n", int(li - lines), ANGLE2DBL(toppitch), ANGLE2DBL(bottompitch));
|
||||
|
||||
if (li->isLinePortal() && frontflag == 0)
|
||||
{
|
||||
EnterLinePortal(li, in->frac);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!(li->flags & ML_TWOSIDED) || (li->flags & ML_BLOCKEVERYTHING))
|
||||
return; // stop
|
||||
|
@ -3599,26 +3809,48 @@ void aim_t::AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t en
|
|||
// Crosses a two sided line.
|
||||
// A two sided line will restrict the possible target ranges.
|
||||
FLineOpening open;
|
||||
P_LineOpening(open, NULL, li, it.Trace().x + FixedMul(it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul(it.Trace().dy, in->frac));
|
||||
P_LineOpening(open, NULL, li, it.InterceptPoint(in), FIXED_MIN, 0, FFCF_NODROPOFF);
|
||||
|
||||
if (open.bottom >= open.top)
|
||||
return; // stop
|
||||
// The following code assumes that portals on the front of the line have already been processed.
|
||||
|
||||
if (open.range <= 0 || open.bottom >= open.top)
|
||||
return;
|
||||
|
||||
dist = FixedMul(attackrange, in->frac);
|
||||
|
||||
if (open.bottom != FIXED_MIN)
|
||||
{
|
||||
pitch = -(int)R_PointToAngle2(0, shootz, dist, open.bottom);
|
||||
if (pitch < bottompitch)
|
||||
bottompitch = pitch;
|
||||
if (pitch < bottompitch) bottompitch = pitch;
|
||||
}
|
||||
|
||||
if (open.top != FIXED_MAX)
|
||||
{
|
||||
pitch = -(int)R_PointToAngle2(0, shootz, dist, open.top);
|
||||
if (pitch > toppitch)
|
||||
toppitch = pitch;
|
||||
if (pitch > toppitch) toppitch = pitch;
|
||||
}
|
||||
|
||||
if (toppitch >= bottompitch)
|
||||
return; // stop
|
||||
return;
|
||||
|
||||
if (!AimTraverse3DFloors(it.Trace(), in)) return;
|
||||
int planestocheck;
|
||||
if (!AimTraverse3DFloors(it.Trace(), in, frontflag, &planestocheck))
|
||||
return;
|
||||
|
||||
Printf("After line %d: toppitch = %f, bottompitch = %f, planestocheck = %d\n", int(li - lines), ANGLE2DBL(toppitch), ANGLE2DBL(bottompitch), planestocheck);
|
||||
|
||||
sector_t *entersec = frontflag ? li->frontsector : li->backsector;
|
||||
sector_t *exitsec = frontflag ? li->backsector : li->frontsector;
|
||||
lastsector = entersec;
|
||||
// check portal in backsector when aiming up/downward is possible, the line doesn't have portals on both sides and there's actually a portal in the backsector
|
||||
if ((planestocheck & aim_up) && toppitch < 0 && open.top != FIXED_MAX && !entersec->PortalBlocksMovement(sector_t::ceiling))
|
||||
{
|
||||
EnterSectorPortal(sector_t::ceiling, in->frac, entersec, toppitch, MIN(0, bottompitch));
|
||||
}
|
||||
if ((planestocheck & aim_down) && bottompitch > 0 && open.bottom != FIXED_MIN && !entersec->PortalBlocksMovement(sector_t::floor))
|
||||
{
|
||||
EnterSectorPortal(sector_t::floor, in->frac, entersec, MAX(0, toppitch), bottompitch);
|
||||
}
|
||||
continue; // shot continues
|
||||
}
|
||||
|
||||
|
@ -3627,7 +3859,7 @@ void aim_t::AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t en
|
|||
if (th == shootthing)
|
||||
continue; // can't shoot self
|
||||
|
||||
if (target != NULL && th != target)
|
||||
if (aimtarget != NULL && th != aimtarget)
|
||||
continue; // only care about target, and you're not it
|
||||
|
||||
// If we want to start a conversation anything that has one should be
|
||||
|
@ -3697,16 +3929,16 @@ void aim_t::AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t en
|
|||
if (crossedffloors)
|
||||
{
|
||||
// if 3D floors were in the way do an extra visibility check for safety
|
||||
if (!P_CheckSight(shootthing, th, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
|
||||
if (!unlinked && !P_CheckSight(shootthing, th, SF_IGNOREVISIBILITY | SF_IGNOREWATERBOUNDARY))
|
||||
{
|
||||
// the thing can't be seen so we can safely exclude its range from our aiming field
|
||||
if (thingtoppitch<toppitch)
|
||||
if (thingtoppitch < toppitch)
|
||||
{
|
||||
if (thingbottompitch>toppitch) toppitch = thingbottompitch;
|
||||
if (thingbottompitch > toppitch) toppitch = thingbottompitch;
|
||||
}
|
||||
else if (thingbottompitch>bottompitch)
|
||||
{
|
||||
if (thingtoppitch<bottompitch) bottompitch = thingtoppitch;
|
||||
if (thingtoppitch < bottompitch) bottompitch = thingtoppitch;
|
||||
}
|
||||
if (toppitch < bottompitch) continue;
|
||||
else return;
|
||||
|
@ -3739,11 +3971,11 @@ void aim_t::AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t en
|
|||
}
|
||||
}
|
||||
|
||||
if ((flags & ALF_NOFRIENDS) && th->IsFriend(friender))
|
||||
if ((flags & ALF_NOFRIENDS) && th->IsFriend(friender) && aimtarget == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (sv_smartaim != 0 && !(flags & ALF_FORCENOSMART))
|
||||
else if (sv_smartaim != 0 && !(flags & ALF_FORCENOSMART) && aimtarget == NULL)
|
||||
{
|
||||
// try to be a little smarter about what to aim at!
|
||||
// In particular avoid autoaiming at friends and barrels.
|
||||
|
@ -3752,8 +3984,8 @@ void aim_t::AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t en
|
|||
if (sv_smartaim < 2)
|
||||
{
|
||||
// friends don't aim at friends (except players), at least not first
|
||||
thing_friend = th;
|
||||
pitch_friend = thingpitch;
|
||||
Printf("Hit friend %s at %f,%f,%f\n", th->GetClass()->TypeName.GetChars(), th->X() / 65536., th->Y() / 65536., th->Z() / 65536.);
|
||||
SetResult(thing_friend, in->frac, th, thingpitch);
|
||||
}
|
||||
}
|
||||
else if (!(th->flags3 & MF3_ISMONSTER) && th->player == NULL)
|
||||
|
@ -3761,25 +3993,26 @@ void aim_t::AimTraverse(fixed_t startx, fixed_t starty, fixed_t endx, fixed_t en
|
|||
if (sv_smartaim < 3)
|
||||
{
|
||||
// don't autoaim at barrels and other shootable stuff unless no monsters have been found
|
||||
thing_other = th;
|
||||
pitch_other = thingpitch;
|
||||
Printf("Hit other %s at %f,%f,%f\n", th->GetClass()->TypeName.GetChars(), th->X() / 65536., th->Y() / 65536., th->Z() / 65536.);
|
||||
SetResult(thing_other, in->frac, th, thingpitch);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
linetarget = th;
|
||||
aimpitch = thingpitch;
|
||||
Printf("Hit target %s at %f,%f,%f\n", th->GetClass()->TypeName.GetChars(), th->X() / 65536., th->Y() / 65536., th->Z() / 65536.);
|
||||
SetResult(linetarget, in->frac, th, thingpitch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
linetarget = th;
|
||||
aimpitch = thingpitch;
|
||||
Printf("Hit target %s at %f,%f,%f\n", th->GetClass()->TypeName.GetChars(), th->X() / 65536., th->Y() / 65536., th->Z() / 65536.);
|
||||
SetResult(linetarget, in->frac, th, thingpitch);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
|
@ -3790,25 +4023,14 @@ 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, FTranslatedLineTarget *pLineTarget, fixed_t vrange,
|
||||
int flags, AActor *target, AActor *friender)
|
||||
{
|
||||
fixed_t x2;
|
||||
fixed_t y2;
|
||||
aim_t aim;
|
||||
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
aim.flags = flags;
|
||||
aim.shootthing = t1;
|
||||
aim.friender = (friender == NULL) ? t1 : friender;
|
||||
|
||||
x2 = t1->X() + (distance >> FRACBITS)*finecosine[angle];
|
||||
y2 = t1->Y() + (distance >> FRACBITS)*finesine[angle];
|
||||
aim.shootz = t1->Z() + (t1->height >> 1) - t1->floorclip;
|
||||
fixed_t shootz = t1->Z() + (t1->height >> 1) - t1->floorclip;
|
||||
if (t1->player != NULL)
|
||||
{
|
||||
aim.shootz += FixedMul(t1->player->mo->AttackZOffset, t1->player->crouchfactor);
|
||||
shootz += FixedMul(t1->player->mo->AttackZOffset, t1->player->crouchfactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
aim.shootz += 8 * FRACUNIT;
|
||||
shootz += 8 * FRACUNIT;
|
||||
}
|
||||
|
||||
// can't shoot outside view angles
|
||||
|
@ -3836,65 +4058,34 @@ fixed_t P_AimLineAttack(AActor *t1, angle_t angle, fixed_t distance, FTranslated
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
aim_t aim;
|
||||
|
||||
aim.flags = flags;
|
||||
aim.shootthing = t1;
|
||||
aim.friender = (friender == NULL) ? t1 : friender;
|
||||
aim.aimdir = aim_t::aim_up | aim_t::aim_down;
|
||||
aim.startpos = t1->Pos();
|
||||
aim.aimtrace = Vec2Angle(distance, angle);
|
||||
aim.limitz = aim.shootz = shootz;
|
||||
aim.toppitch = t1->pitch - vrange;
|
||||
aim.bottompitch = t1->pitch + vrange;
|
||||
|
||||
aim.attackrange = distance;
|
||||
aim.linetarget = NULL;
|
||||
|
||||
// for smart aiming
|
||||
aim.thing_friend = aim.thing_other = NULL;
|
||||
|
||||
// Information for tracking crossed 3D floors
|
||||
aim.aimpitch = t1->pitch;
|
||||
|
||||
aim.crossedffloors = t1->Sector->e->XFloor.ffloors.Size() != 0;
|
||||
aim.lastsector = t1->Sector;
|
||||
aim.lastfloorplane = aim.lastceilingplane = NULL;
|
||||
aim.startfrac = 0;
|
||||
aim.unlinked = false;
|
||||
aim.aimtarget = target;
|
||||
|
||||
// set initial 3d-floor info
|
||||
for (unsigned i = 0; i<t1->Sector->e->XFloor.ffloors.Size(); i++)
|
||||
{
|
||||
F3DFloor * rover = t1->Sector->e->XFloor.ffloors[i];
|
||||
fixed_t bottomz = rover->bottom.plane->ZatPoint(t1);
|
||||
aim.AimTraverse();
|
||||
|
||||
if (bottomz >= t1->Top()) aim.lastceilingplane = rover->bottom.plane;
|
||||
AimTarget *result = aim.Result();
|
||||
|
||||
bottomz = rover->top.plane->ZatPoint(t1);
|
||||
if (bottomz <= t1->Z()) aim.lastfloorplane = rover->top.plane;
|
||||
}
|
||||
|
||||
aim.AimTraverse(t1->X(), t1->Y(), x2, y2, target);
|
||||
|
||||
if (!aim.linetarget)
|
||||
{
|
||||
if (aim.thing_other)
|
||||
{
|
||||
aim.linetarget = aim.thing_other;
|
||||
aim.aimpitch = aim.pitch_other;
|
||||
}
|
||||
else if (aim.thing_friend)
|
||||
{
|
||||
aim.linetarget = aim.thing_friend;
|
||||
aim.aimpitch = aim.pitch_friend;
|
||||
}
|
||||
}
|
||||
if (pLineTarget)
|
||||
{
|
||||
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;
|
||||
*pLineTarget = *result;
|
||||
}
|
||||
else
|
||||
memset(pLineTarget, 0, sizeof(*pLineTarget));
|
||||
}
|
||||
return aim.linetarget ? aim.aimpitch : t1->pitch;
|
||||
return result->linetarget ? result->pitch : t1->pitch;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4188,11 +4379,7 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
|
|||
if (victim != NULL)
|
||||
{
|
||||
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->angleFromSource = R_PointToAngle2(t1->X(), t1->Y(), trace.Actor->X(), trace.Actor->Y());
|
||||
victim->unlinked = false;
|
||||
}
|
||||
}
|
||||
|
@ -4422,7 +4609,7 @@ void P_TraceBleed(int damage, FTranslatedLineTarget *t, AActor *puff)
|
|||
|
||||
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);
|
||||
t->linetarget, t->angleFromSource, 0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -4795,8 +4982,7 @@ bool P_UseTraverse(AActor *usething, fixed_t startx, fixed_t starty, fixed_t end
|
|||
}
|
||||
else
|
||||
{
|
||||
P_LineOpening(open, NULL, in->d.line, it.Trace().x + FixedMul(it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul(it.Trace().dy, in->frac));
|
||||
P_LineOpening(open, NULL, in->d.line, it.InterceptPoint(in));
|
||||
}
|
||||
if (open.range <= 0 ||
|
||||
(in->d.line->special != 0 && (i_compatflags & COMPATF_USEBLOCKING)))
|
||||
|
@ -4904,8 +5090,7 @@ bool P_NoWayTraverse(AActor *usething, fixed_t startx, fixed_t starty, fixed_t e
|
|||
if (ld->special) continue;
|
||||
if (ld->isLinePortal()) return false;
|
||||
if (ld->flags&(ML_BLOCKING | ML_BLOCKEVERYTHING | ML_BLOCK_PLAYERS)) return true;
|
||||
P_LineOpening(open, NULL, ld, it.Trace().x + FixedMul(it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul(it.Trace().dy, in->frac));
|
||||
P_LineOpening(open, NULL, ld, it.InterceptPoint(in));
|
||||
if (open.range <= 0 ||
|
||||
open.bottom > usething->Z() + usething->MaxStepHeight ||
|
||||
open.top < usething->Top()) return true;
|
||||
|
@ -4989,8 +5174,7 @@ bool P_UsePuzzleItem(AActor *PuzzleItemUser, int PuzzleItemType)
|
|||
{ // Check line
|
||||
if (in->d.line->special != UsePuzzleItem)
|
||||
{
|
||||
P_LineOpening(open, NULL, in->d.line, it.Trace().x + FixedMul(it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul(it.Trace().dy, in->frac));
|
||||
P_LineOpening(open, NULL, in->d.line, it.InterceptPoint(in));
|
||||
if (open.range <= 0)
|
||||
{
|
||||
return false; // can't use through a wall
|
||||
|
|
|
@ -210,7 +210,7 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
|
|||
open.floorpic = front->GetTexture(sector_t::floor);
|
||||
open.floorterrain = front->GetTerrain(sector_t::floor);
|
||||
if (bf != FIXED_MIN) open.lowfloor = bf;
|
||||
else
|
||||
else if (!(flags & FFCF_NODROPOFF))
|
||||
{
|
||||
// We must check through the portal for the actual dropoff.
|
||||
// If there's no lines in the lower sections we'd never get a usable value otherwise.
|
||||
|
@ -224,7 +224,7 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
|
|||
open.floorpic = back->GetTexture(sector_t::floor);
|
||||
open.floorterrain = back->GetTerrain(sector_t::floor);
|
||||
if (ff != FIXED_MIN) open.lowfloor = ff;
|
||||
else
|
||||
else if (!(flags & FFCF_NODROPOFF))
|
||||
{
|
||||
// We must check through the portal for the actual dropoff.
|
||||
// If there's no lines in the lower sections we'd never get a usable value otherwise.
|
||||
|
@ -264,7 +264,8 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
|
|||
open.abovemidtex = open.touchmidtex = false;
|
||||
}
|
||||
|
||||
open.range = open.top - open.bottom;
|
||||
// avoid overflows in the opening.
|
||||
open.range = (fixed_t)MIN<QWORD>((QWORD)open.top - open.bottom, FIXED_MAX);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1286,9 +1287,33 @@ void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it
|
|||
fixed_t frac = P_InterceptVector (&trace, &line);
|
||||
if (frac < startfrac)
|
||||
{ // behind source
|
||||
if (startfrac > 0)
|
||||
{
|
||||
// check if the trace starts within this actor
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
line.y -= 2 * thing->radius;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
line.x -= 2 * thing->radius;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
line.y += 2 * thing->radius;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
line.x += 2 * thing->radius;
|
||||
break;
|
||||
}
|
||||
fixed_t frac2 = P_InterceptVector(&trace, &line);
|
||||
if (frac2 >= startfrac) goto addit;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
addit:
|
||||
intercept_t newintercept;
|
||||
newintercept.frac = frac;
|
||||
newintercept.isaline = false;
|
||||
|
@ -1422,16 +1447,6 @@ void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int fl
|
|||
|
||||
int count;
|
||||
|
||||
validcount++;
|
||||
intercept_index = intercepts.Size();
|
||||
this->startfrac = startfrac;
|
||||
|
||||
if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
|
||||
x1 += FRACUNIT; // don't side exactly on a line
|
||||
|
||||
if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0)
|
||||
y1 += FRACUNIT; // don't side exactly on a line
|
||||
|
||||
trace.x = x1;
|
||||
trace.y = y1;
|
||||
if (flags & PT_DELTA)
|
||||
|
@ -1444,9 +1459,30 @@ void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int fl
|
|||
trace.dx = x2 - x1;
|
||||
trace.dy = y2 - y1;
|
||||
}
|
||||
if (startfrac > 0)
|
||||
{
|
||||
fixed_t startdx = FixedMul(trace.dx, startfrac);
|
||||
fixed_t startdy = FixedMul(trace.dy, startfrac);
|
||||
|
||||
_x1 = (long long)x1 + FixedMul(trace.dx, startfrac) - bmaporgx;
|
||||
_y1 = (long long)y1 + FixedMul(trace.dy, startfrac) - bmaporgy;
|
||||
x1 += startdx;
|
||||
y1 += startdy;
|
||||
x2 = trace.dx - startdx;
|
||||
y2 = trace.dy - startdy;
|
||||
flags |= PT_DELTA;
|
||||
}
|
||||
|
||||
validcount++;
|
||||
intercept_index = intercepts.Size();
|
||||
this->startfrac = startfrac;
|
||||
|
||||
if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
|
||||
x1 += FRACUNIT; // don't side exactly on a line
|
||||
|
||||
if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0)
|
||||
y1 += FRACUNIT; // don't side exactly on a line
|
||||
|
||||
_x1 = (long long)x1 - bmaporgx;
|
||||
_y1 = (long long)y1 - bmaporgy;
|
||||
x1 -= bmaporgx;
|
||||
y1 -= bmaporgy;
|
||||
xt1 = int(_x1 >> MAPBLOCKSHIFT);
|
||||
|
@ -1615,7 +1651,7 @@ void FPathTraverse::init (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int fl
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
bool FPathTraverse::PortalRelocate(intercept_t *in, int flags, fixedvec3 *optpos)
|
||||
int FPathTraverse::PortalRelocate(intercept_t *in, int flags, fixedvec3 *optpos)
|
||||
{
|
||||
if (!in->isaline || !in->d.line->isLinePortal()) return false;
|
||||
if (P_PointOnLineSidePrecise(trace.x, trace.y, in->d.line) == 1) return false;
|
||||
|
@ -1635,7 +1671,7 @@ bool FPathTraverse::PortalRelocate(intercept_t *in, int flags, fixedvec3 *optpos
|
|||
}
|
||||
intercepts.Resize(intercept_index);
|
||||
init(hitx, hity, endx, endy, flags, in->frac);
|
||||
return true;
|
||||
return in->d.line->getPortal()->mType == PORTT_LINKED? 1:-1;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -26,7 +26,6 @@ struct intercept_t
|
|||
} d;
|
||||
};
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_PointOnLineSide
|
||||
|
@ -107,6 +106,10 @@ struct FLineOpening
|
|||
};
|
||||
|
||||
void P_LineOpening (FLineOpening &open, AActor *thing, const line_t *linedef, fixed_t x, fixed_t y, fixed_t refx=FIXED_MIN, fixed_t refy=0, int flags=0);
|
||||
inline void P_LineOpening(FLineOpening &open, AActor *thing, const line_t *linedef, fixedvec2 xy, fixed_t refx = FIXED_MIN, fixed_t refy = 0, int flags = 0)
|
||||
{
|
||||
P_LineOpening(open, thing, linedef, xy.x, xy.y, refx, refy, flags);
|
||||
}
|
||||
|
||||
class FBoundingBox;
|
||||
struct polyblock_t;
|
||||
|
@ -351,14 +354,24 @@ public:
|
|||
|
||||
intercept_t *Next();
|
||||
|
||||
FPathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags)
|
||||
FPathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, fixed_t startfrac = 0)
|
||||
{
|
||||
init(x1, y1, x2, y2, flags);
|
||||
init(x1, y1, x2, y2, flags, startfrac);
|
||||
}
|
||||
void init(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, fixed_t startfrac = 0);
|
||||
bool PortalRelocate(intercept_t *in, int flags, fixedvec3 *optpos = NULL);
|
||||
int PortalRelocate(intercept_t *in, int flags, fixedvec3 *optpos = NULL);
|
||||
virtual ~FPathTraverse();
|
||||
const divline_t &Trace() const { return trace; }
|
||||
|
||||
inline fixedvec2 InterceptPoint(const intercept_t *in)
|
||||
{
|
||||
return
|
||||
{
|
||||
trace.x + FixedMul(trace.dx, in->frac),
|
||||
trace.y + FixedMul(trace.dy, in->frac)
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
|
|
@ -709,14 +709,13 @@ fixedvec2 P_GetOffsetPosition(fixed_t x, fixed_t y, fixed_t dx, fixed_t dy)
|
|||
// Teleport portals are intentionally ignored since skipping this stuff is their entire reason for existence.
|
||||
if (port->mFlags & PORTF_INTERACTIVE)
|
||||
{
|
||||
fixed_t hitdx = FixedMul(it.Trace().dx, in->frac);
|
||||
fixed_t hitdy = FixedMul(it.Trace().dy, in->frac);
|
||||
fixedvec2 hit = it.InterceptPoint(in);
|
||||
|
||||
if (port->mType == PORTT_LINKED)
|
||||
{
|
||||
// optimized handling for linked portals where we only need to add an offset.
|
||||
actx = it.Trace().x + hitdx + port->mXDisplacement;
|
||||
acty = it.Trace().y + hitdy + port->mYDisplacement;
|
||||
hit.x += port->mXDisplacement;
|
||||
hit.y += port->mYDisplacement;
|
||||
dest.x += port->mXDisplacement;
|
||||
dest.y += port->mYDisplacement;
|
||||
}
|
||||
|
@ -724,15 +723,12 @@ fixedvec2 P_GetOffsetPosition(fixed_t x, fixed_t y, fixed_t dx, fixed_t dy)
|
|||
{
|
||||
// interactive ones are more complex because the vector may be rotated.
|
||||
// Note: There is no z-translation here, there's just too much code in the engine that wouldn't be able to handle interactive portals with a height difference.
|
||||
actx = it.Trace().x + hitdx;
|
||||
acty = it.Trace().y + hitdy;
|
||||
|
||||
P_TranslatePortalXY(line, out, actx, acty);
|
||||
P_TranslatePortalXY(line, out, hit.x, hit.y);
|
||||
P_TranslatePortalXY(line, out, dest.x, dest.y);
|
||||
}
|
||||
// update the fields, end this trace and restart from the new position
|
||||
dx = dest.x - actx;
|
||||
dy = dest.y - acty;
|
||||
dx = dest.x - hit.x;
|
||||
dy = dest.y - hit.y;
|
||||
repeat = true;
|
||||
}
|
||||
|
||||
|
@ -1108,9 +1104,16 @@ bool P_CollectConnectedGroups(int startgroup, const fixedvec3 &position, fixed_t
|
|||
|
||||
bool retval = false;
|
||||
out.inited = true;
|
||||
|
||||
processMask.setSize(Displacements.size);
|
||||
if (Displacements.size == 1)
|
||||
{
|
||||
processMask.setBit(startgroup);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (linkedPortals.Size() != 0)
|
||||
{
|
||||
processMask.setSize(linkedPortals.Size());
|
||||
processMask.clear();
|
||||
foundPortals.Clear();
|
||||
|
||||
|
|
|
@ -360,8 +360,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, GetGibHealth)
|
|||
//===========================================================================
|
||||
//
|
||||
// __decorate_internal_state__
|
||||
// __decorate_internal_int__
|
||||
// __decorate_internal_bool__
|
||||
// __decorate_internal_float__
|
||||
//
|
||||
// Returns the state passed in.
|
||||
// Placeholders for forcing DECORATE to cast numbers. If actually called,
|
||||
// returns whatever was passed.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
|
@ -373,14 +377,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_state__)
|
|||
ACTION_RETURN_STATE(returnme);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// __decorate_internal_int__
|
||||
//
|
||||
// Returns the int passed in.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_int__)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
|
@ -389,14 +385,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_int__)
|
|||
ACTION_RETURN_INT(returnme);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// __decorate_internal_bool__
|
||||
//
|
||||
// Returns the bool passed in.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_bool__)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
|
@ -405,6 +393,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_bool__)
|
|||
ACTION_RETURN_BOOL(returnme);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, __decorate_internal_float__)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_OBJECT(self, AActor);
|
||||
PARAM_FLOAT(returnme);
|
||||
if (numret > 0)
|
||||
{
|
||||
ret->SetFloat(returnme);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_RearrangePointers
|
||||
|
@ -1796,7 +1797,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomPunch)
|
|||
if (!(flags & CPF_NOTURN))
|
||||
{
|
||||
// turn to face target
|
||||
self->angle = t.SourceAngleToTarget();
|
||||
self->angle = t.angleFromSource;
|
||||
}
|
||||
|
||||
if (flags & CPF_PULLIN) self->flags |= MF_JUSTATTACKED;
|
||||
|
|
|
@ -3420,7 +3420,8 @@ bool FxVMFunctionCall::CheckEmitCast(VMFunctionBuilder *build, bool returnit, Ex
|
|||
FName funcname = Function->SymbolName;
|
||||
if (funcname == NAME___decorate_internal_int__ ||
|
||||
funcname == NAME___decorate_internal_bool__ ||
|
||||
funcname == NAME___decorate_internal_state__)
|
||||
funcname == NAME___decorate_internal_state__ ||
|
||||
funcname == NAME___decorate_internal_float__)
|
||||
{
|
||||
FxExpression *arg = (*ArgList)[0];
|
||||
if (returnit)
|
||||
|
|
|
@ -711,6 +711,8 @@ FName CheckCastKludges(FName in)
|
|||
return NAME___decorate_internal_bool__;
|
||||
case NAME_State:
|
||||
return NAME___decorate_internal_state__;
|
||||
case NAME_Float:
|
||||
return NAME___decorate_internal_float__;
|
||||
default:
|
||||
return in;
|
||||
}
|
||||
|
|
|
@ -356,4 +356,5 @@ ACTOR Actor native //: Thinker
|
|||
native state __decorate_internal_state__(state);
|
||||
native int __decorate_internal_int__(int);
|
||||
native bool __decorate_internal_bool__(bool);
|
||||
native float __decorate_internal_float__(float);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue