- Update scripting branch to trunk.
SVN r3758 (scripting)
This commit is contained in:
commit
562cf04db2
614 changed files with 63691 additions and 31256 deletions
249
src/p_enemy.cpp
249
src/p_enemy.cpp
|
|
@ -44,6 +44,7 @@
|
|||
#include "thingdef/thingdef.h"
|
||||
#include "d_dehacked.h"
|
||||
#include "g_level.h"
|
||||
#include "teaminfo.h"
|
||||
|
||||
#include "gi.h"
|
||||
|
||||
|
|
@ -114,7 +115,7 @@ void P_RandomChaseDir (AActor *actor);
|
|||
// sound blocking lines cut off traversal.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void P_RecursiveSound (sector_t *sec, AActor *soundtarget, bool splash, int soundblocks)
|
||||
void P_RecursiveSound (sector_t *sec, AActor *soundtarget, bool splash, int soundblocks, AActor *emitter, fixed_t maxdist)
|
||||
{
|
||||
int i;
|
||||
line_t* check;
|
||||
|
|
@ -135,7 +136,8 @@ void P_RecursiveSound (sector_t *sec, AActor *soundtarget, bool splash, int soun
|
|||
// [RH] Set this in the actors in the sector instead of the sector itself.
|
||||
for (actor = sec->thinglist; actor != NULL; actor = actor->snext)
|
||||
{
|
||||
if (actor != soundtarget && (!splash || !(actor->flags4 & MF4_NOSPLASHALERT)))
|
||||
if (actor != soundtarget && (!splash || !(actor->flags4 & MF4_NOSPLASHALERT)) &&
|
||||
(!maxdist || (P_AproxDistance(actor->x - emitter->x, actor->y - emitter->y) <= maxdist)))
|
||||
{
|
||||
actor->LastHeard = soundtarget;
|
||||
}
|
||||
|
|
@ -178,11 +180,11 @@ void P_RecursiveSound (sector_t *sec, AActor *soundtarget, bool splash, int soun
|
|||
if (check->flags & ML_SOUNDBLOCK)
|
||||
{
|
||||
if (!soundblocks)
|
||||
P_RecursiveSound (other, soundtarget, splash, 1);
|
||||
P_RecursiveSound (other, soundtarget, splash, 1, emitter, maxdist);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_RecursiveSound (other, soundtarget, splash, soundblocks);
|
||||
P_RecursiveSound (other, soundtarget, splash, soundblocks, emitter, maxdist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -198,7 +200,7 @@ void P_RecursiveSound (sector_t *sec, AActor *soundtarget, bool splash, int soun
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void P_NoiseAlert (AActor *target, AActor *emitter, bool splash)
|
||||
void P_NoiseAlert (AActor *target, AActor *emitter, bool splash, fixed_t maxdist)
|
||||
{
|
||||
if (emitter == NULL)
|
||||
return;
|
||||
|
|
@ -207,7 +209,7 @@ void P_NoiseAlert (AActor *target, AActor *emitter, bool splash)
|
|||
return;
|
||||
|
||||
validcount++;
|
||||
P_RecursiveSound (emitter->Sector, target, splash, 0);
|
||||
P_RecursiveSound (emitter->Sector, target, splash, 0, emitter, maxdist);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -308,7 +310,7 @@ bool P_CheckMissileRange (AActor *actor)
|
|||
{
|
||||
fixed_t dist;
|
||||
|
||||
if (!P_CheckSight (actor, actor->target, SF_SEEPASTBLOCKEVERYTHING|SF_SEEPASTSHOOTABLELINES))
|
||||
if (!P_CheckSight (actor, actor->target, SF_SEEPASTBLOCKEVERYTHING))
|
||||
return false;
|
||||
|
||||
if (actor->flags & MF_JUSTHIT)
|
||||
|
|
@ -427,20 +429,14 @@ bool P_Move (AActor *actor)
|
|||
return false;
|
||||
}
|
||||
|
||||
// [RH] Instead of yanking non-floating monsters to the ground,
|
||||
// let gravity drop them down, unless they're moving down a step.
|
||||
// [RH] Walking actors that are not on the ground cannot walk. We don't
|
||||
// want to yank them to the ground here as Doom did, since that makes
|
||||
// it difficult to thrust them vertically in a reasonable manner.
|
||||
// [GZ] Let jumping actors jump.
|
||||
if (!((actor->flags & MF_NOGRAVITY) || (actor->flags6 & MF6_CANJUMP))
|
||||
&& actor->z > actor->floorz && !(actor->flags2 & MF2_ONMOBJ))
|
||||
{
|
||||
if (actor->z > actor->floorz + actor->MaxStepHeight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
actor->z = actor->floorz;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((unsigned)actor->movedir >= 8)
|
||||
|
|
@ -537,6 +533,26 @@ bool P_Move (AActor *actor)
|
|||
actor->vely += FixedMul (deltay, movefactor);
|
||||
}
|
||||
|
||||
// [RH] If a walking monster is no longer on the floor, move it down
|
||||
// to the floor if it is within MaxStepHeight, presuming that it is
|
||||
// actually walking down a step.
|
||||
if (try_ok &&
|
||||
!((actor->flags & MF_NOGRAVITY) || (actor->flags6 & MF6_CANJUMP))
|
||||
&& actor->z > actor->floorz && !(actor->flags2 & MF2_ONMOBJ))
|
||||
{
|
||||
if (actor->z <= actor->floorz + actor->MaxStepHeight)
|
||||
{
|
||||
fixed_t savedz = actor->z;
|
||||
actor->z = actor->floorz;
|
||||
// Make sure that there isn't some other actor between us and
|
||||
// the floor we could get stuck in. The old code did not do this.
|
||||
if (!P_TestMobjZ(actor))
|
||||
{
|
||||
actor->z = savedz;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!try_ok)
|
||||
{
|
||||
if (((actor->flags6 & MF6_CANJUMP)||(actor->flags & MF_FLOAT)) && tm.floatok)
|
||||
|
|
@ -1111,7 +1127,7 @@ bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams
|
|||
else
|
||||
{
|
||||
mindist = maxdist = 0;
|
||||
fov = allaround? 0 : ANGLE_180;
|
||||
fov = allaround ? 0 : ANGLE_180;
|
||||
}
|
||||
|
||||
fixed_t dist = P_AproxDistance (other->x - lookee->x, other->y - lookee->y);
|
||||
|
|
@ -1136,7 +1152,7 @@ bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams
|
|||
}
|
||||
|
||||
// P_CheckSight is by far the most expensive operation in here so let's do it last.
|
||||
return P_CheckSight(lookee, other, SF_SEEPASTBLOCKEVERYTHING);
|
||||
return P_CheckSight(lookee, other, SF_SEEPASTSHOOTABLELINES);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
@ -1403,9 +1419,7 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index, void *extparam)
|
|||
other = NULL;
|
||||
if (link->flags & MF_FRIENDLY)
|
||||
{
|
||||
if (deathmatch &&
|
||||
lookee->FriendPlayer != 0 && link->FriendPlayer != 0 &&
|
||||
lookee->FriendPlayer != link->FriendPlayer)
|
||||
if (!lookee->IsFriend(link))
|
||||
{
|
||||
// This is somebody else's friend, so go after it
|
||||
other = link;
|
||||
|
|
@ -1567,7 +1581,7 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params)
|
|||
}
|
||||
#endif
|
||||
// [SP] If you don't see any enemies in deathmatch, look for players (but only when friend to a specific player.)
|
||||
if (actor->FriendPlayer == 0) return result;
|
||||
if (actor->FriendPlayer == 0 && (!teamplay || actor->DesignatedTeam == TEAM_NONE)) return result;
|
||||
if (result || !deathmatch) return true;
|
||||
|
||||
|
||||
|
|
@ -1650,25 +1664,28 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params)
|
|||
// We're going to ignore our master, but go after his enemies.
|
||||
if ( actor->flags & MF_FRIENDLY )
|
||||
{
|
||||
if ( actor->FriendPlayer == 0 )
|
||||
continue; // I have no friends, I will ignore players.
|
||||
if ( actor->FriendPlayer == player->mo->FriendPlayer )
|
||||
continue; // This is my master.
|
||||
if ( actor->IsFriend(player->mo) )
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) ||
|
||||
player->mo->flags3 & MF3_GHOST)
|
||||
// [RC] Well, let's let special monsters with this flag active be able to see
|
||||
// the player then, eh?
|
||||
if(!(actor->flags & MF6_SEEINVISIBLE))
|
||||
{
|
||||
if ((P_AproxDistance (player->mo->x - actor->x,
|
||||
player->mo->y - actor->y) > 2*MELEERANGE)
|
||||
&& P_AproxDistance (player->mo->velx, player->mo->vely)
|
||||
< 5*FRACUNIT)
|
||||
{ // Player is sneaking - can't detect
|
||||
return false;
|
||||
}
|
||||
if (pr_lookforplayers() < 225)
|
||||
{ // Player isn't sneaking, but still didn't detect
|
||||
return false;
|
||||
if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) ||
|
||||
player->mo->flags3 & MF3_GHOST)
|
||||
{
|
||||
if ((P_AproxDistance (player->mo->x - actor->x,
|
||||
player->mo->y - actor->y) > 2*MELEERANGE)
|
||||
&& P_AproxDistance (player->mo->velx, player->mo->vely)
|
||||
< 5*FRACUNIT)
|
||||
{ // Player is sneaking - can't detect
|
||||
return false;
|
||||
}
|
||||
if (pr_lookforplayers() < 225)
|
||||
{ // Player isn't sneaking, but still didn't detect
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1818,11 +1835,12 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
|
|||
PARAM_FIXED_OPT (minseedist) { minseedist = 0; }
|
||||
PARAM_FIXED_OPT (maxseedist) { maxseedist = 0; }
|
||||
PARAM_FIXED_OPT (maxheardist) { maxheardist = 0; }
|
||||
PARAM_ANGLE_OPT (fov) { fov = 0; }
|
||||
PARAM_FLOAT_OPT (fov_f) { fov_f = 0; }
|
||||
PARAM_STATE_OPT (seestate) { seestate = NULL; }
|
||||
|
||||
AActor *targ = NULL; // Shuts up gcc
|
||||
fixed_t dist;
|
||||
angle_t fov = (fov_f == 0) ? ANGLE_180 : angle_t(fov_f * ANGLE_90 / 90);
|
||||
FLookExParams params = { fov, minseedist, maxseedist, maxheardist, flags, seestate };
|
||||
|
||||
if (self->flags5 & MF5_INCONVERSATION)
|
||||
|
|
@ -1995,6 +2013,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx)
|
|||
|
||||
// [KS] *** End additions by me ***
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_ClearLastHeard
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_ClearLastHeard)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
self->LastHeard = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_Wander
|
||||
|
|
@ -2162,10 +2193,13 @@ void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *mele
|
|||
|
||||
if (nightmarefast && G_SkillProperty(SKILLP_FastMonsters))
|
||||
{ // Monsters move faster in nightmare mode
|
||||
actor->tics -= actor->tics / 2;
|
||||
if (actor->tics < 3)
|
||||
if (actor->tics > 3)
|
||||
{
|
||||
actor->tics = 3;
|
||||
actor->tics -= actor->tics / 2;
|
||||
if (actor->tics < 3)
|
||||
{
|
||||
actor->tics = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2291,7 +2325,7 @@ void A_DoChase (VMFrameStack *stack, AActor *actor, bool fastchase, FState *mele
|
|||
// as the goal.
|
||||
while ( (spec = specit.Next()) )
|
||||
{
|
||||
LineSpecials[spec->special] (NULL, actor, false, spec->args[0],
|
||||
P_ExecuteSpecial(spec->special, NULL, actor, false, spec->args[0],
|
||||
spec->args[1], spec->args[2], spec->args[3], spec->args[4]);
|
||||
}
|
||||
|
||||
|
|
@ -2510,6 +2544,25 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
|
|||
if ( abs(corpsehit-> x - viletryx) > maxdist ||
|
||||
abs(corpsehit-> y - viletryy) > maxdist )
|
||||
continue; // not actually touching
|
||||
#ifdef _3DFLOORS
|
||||
// Let's check if there are floors in between the archvile and its target
|
||||
sector_t *vilesec = self->Sector;
|
||||
sector_t *corpsec = corpsehit->Sector;
|
||||
// We only need to test if at least one of the sectors has a 3D floor.
|
||||
sector_t *testsec = vilesec->e->XFloor.ffloors.Size() ? vilesec :
|
||||
(vilesec != corpsec && corpsec->e->XFloor.ffloors.Size()) ? corpsec : NULL;
|
||||
if (testsec)
|
||||
{
|
||||
fixed_t zdist1, zdist2;
|
||||
if (P_Find3DFloor(testsec, corpsehit->x, corpsehit->y, corpsehit->z, false, true, zdist1)
|
||||
!= P_Find3DFloor(testsec, self->x, self->y, self->z, false, true, zdist2))
|
||||
{
|
||||
// Not on same floor
|
||||
if (vilesec == corpsec || abs(zdist1 - self->z) > self->height)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
corpsehit->velx = corpsehit->vely = 0;
|
||||
// [RH] Check against real height and radius
|
||||
|
|
@ -2645,7 +2698,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Chase)
|
|||
}
|
||||
else // this is the old default A_Chase
|
||||
{
|
||||
A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, !!(gameinfo.gametype & GAME_Raven), false);
|
||||
A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2661,7 +2714,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_VileChase)
|
|||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
if (!P_CheckForResurrection(self, true))
|
||||
A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, !!(gameinfo.gametype & GAME_Raven), false);
|
||||
{
|
||||
A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2683,17 +2738,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ExtChase)
|
|||
// for internal use
|
||||
void A_Chase(VMFrameStack *stack, AActor *self)
|
||||
{
|
||||
A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, !!(gameinfo.gametype & GAME_Raven), false);
|
||||
A_DoChase(stack, self, false, self->MeleeState, self->MissileState, true, gameinfo.nightmarefast, false);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// A_FaceTarget
|
||||
// A_FaceMaster
|
||||
// A_FaceTracer
|
||||
//
|
||||
//=============================================================================
|
||||
void A_FaceTarget (AActor *self, angle_t max_turn)
|
||||
void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch)
|
||||
{
|
||||
if (!self->target)
|
||||
if (!other)
|
||||
return;
|
||||
|
||||
// [RH] Andy Baker's stealth monsters
|
||||
|
|
@ -2704,15 +2761,15 @@ void A_FaceTarget (AActor *self, angle_t max_turn)
|
|||
|
||||
self->flags &= ~MF_AMBUSH;
|
||||
|
||||
angle_t target_angle = R_PointToAngle2 (self->x, self->y, self->target->x, self->target->y);
|
||||
angle_t other_angle = R_PointToAngle2 (self->x, self->y, other->x, other->y);
|
||||
|
||||
// 0 means no limit. Also, if we turn in a single step anyways, no need to go through the algorithms.
|
||||
// It also means that there is no need to check for going past the target.
|
||||
if (max_turn && (max_turn < (angle_t)abs(self->angle - target_angle)))
|
||||
// It also means that there is no need to check for going past the other.
|
||||
if (max_turn && (max_turn < (angle_t)abs(self->angle - other_angle)))
|
||||
{
|
||||
if (self->angle > target_angle)
|
||||
if (self->angle > other_angle)
|
||||
{
|
||||
if (self->angle - target_angle < ANGLE_180)
|
||||
if (self->angle - other_angle < ANGLE_180)
|
||||
{
|
||||
self->angle -= max_turn;
|
||||
}
|
||||
|
|
@ -2723,7 +2780,7 @@ void A_FaceTarget (AActor *self, angle_t max_turn)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (target_angle - self->angle < ANGLE_180)
|
||||
if (other_angle - self->angle < ANGLE_180)
|
||||
{
|
||||
self->angle += max_turn;
|
||||
}
|
||||
|
|
@ -2735,22 +2792,90 @@ void A_FaceTarget (AActor *self, angle_t max_turn)
|
|||
}
|
||||
else
|
||||
{
|
||||
self->angle = target_angle;
|
||||
self->angle = other_angle;
|
||||
}
|
||||
|
||||
// [DH] Now set pitch. In order to maintain compatibility, this can be
|
||||
// disabled and is so by default.
|
||||
if (max_pitch <= ANGLE_180)
|
||||
{
|
||||
// [DH] Don't need to do proper fixed->double conversion, since the
|
||||
// result is only used in a ratio.
|
||||
double dist_x = self->target->x - self->x;
|
||||
double dist_y = self->target->y - self->y;
|
||||
double dist_z = self->target->z - self->z;
|
||||
double dist = sqrt(dist_x*dist_x + dist_y*dist_y + dist_z*dist_z);
|
||||
|
||||
int other_pitch = (int)rad2bam(asin(dist_z / dist));
|
||||
|
||||
if (max_pitch != 0)
|
||||
{
|
||||
if (self->pitch > other_pitch)
|
||||
{
|
||||
max_pitch = MIN(max_pitch, unsigned(self->pitch - other_pitch));
|
||||
self->pitch -= max_pitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
max_pitch = MIN(max_pitch, unsigned(other_pitch - self->pitch));
|
||||
self->pitch += max_pitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self->pitch = other_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
// This will never work well if the turn angle is limited.
|
||||
if (max_turn == 0 && (self->angle == target_angle) && self->target->flags & MF_SHADOW)
|
||||
if (max_turn == 0 && (self->angle == other_angle) && other->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE) )
|
||||
{
|
||||
self->angle += pr_facetarget.Random2() << 21;
|
||||
}
|
||||
}
|
||||
|
||||
void A_FaceTarget (AActor *self, angle_t max_turn, angle_t max_pitch)
|
||||
{
|
||||
A_Face(self, self->target, max_turn, max_pitch);
|
||||
}
|
||||
|
||||
void A_FaceMaster (AActor *self, angle_t max_turn, angle_t max_pitch)
|
||||
{
|
||||
A_Face(self, self->master, max_turn, max_pitch);
|
||||
}
|
||||
|
||||
void A_FaceTracer (AActor *self, angle_t max_turn, angle_t max_pitch)
|
||||
{
|
||||
A_Face(self, self->tracer, max_turn, max_pitch);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTarget)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_ANGLE_OPT(max_turn) { max_turn = 0; }
|
||||
PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270; }
|
||||
|
||||
A_FaceTarget(self);
|
||||
A_FaceTarget(self, max_turn, max_pitch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceMaster)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_ANGLE_OPT(max_turn) { max_turn = 0; }
|
||||
PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270; }
|
||||
|
||||
A_FaceMaster(self, max_turn, max_pitch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_FaceTracer)
|
||||
{
|
||||
PARAM_ACTION_PROLOGUE;
|
||||
PARAM_ANGLE_OPT(max_turn) { max_turn = 0; }
|
||||
PARAM_ANGLE_OPT(max_pitch) { max_pitch = 270; }
|
||||
|
||||
A_FaceTracer(self, max_turn, max_pitch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2800,10 +2925,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_MonsterRail)
|
|||
self->target->x - self->target->velx * 3,
|
||||
self->target->y - self->target->vely * 3);
|
||||
|
||||
if (self->target->flags & MF_SHADOW)
|
||||
{
|
||||
if (self->target->flags & MF_SHADOW && !(self->flags6 & MF6_SEEINVISIBLE))
|
||||
{
|
||||
self->angle += pr_railface.Random2() << 21;
|
||||
}
|
||||
}
|
||||
|
||||
P_RailAttack (self, self->GetMissileDamage (0, 1), 0);
|
||||
self->pitch = saved_pitch;
|
||||
|
|
@ -3145,7 +3270,7 @@ void A_BossDeath(AActor *self)
|
|||
}
|
||||
checked = true;
|
||||
|
||||
LineSpecials[sa->Action](NULL, self, false,
|
||||
P_ExecuteSpecial(sa->Action, NULL, self, false,
|
||||
sa->Args[0], sa->Args[1], sa->Args[2], sa->Args[3], sa->Args[4]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue