From f0d3820dd50c4a3a6a8f3c6b753ca8d656b539ee Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 16 Sep 2009 21:17:17 +0000 Subject: [PATCH] Update to ZDoom r1848: - Fixed: The deprecated flag handler for the old bounce flags needs to clear BOUNCE_MBF and BOUNCE_UseSeeSound, too, when clearing one of these flags. - Fixed: When adding the AVOIDMELEE code the code was accidentally changed so that friendly monsters could no longer acquire targets by themselves. - Renamed WIF_BOT_MELEE to WIF_MELEEWEAPON because it's no longer a bot only flag. - Added MBF's monster_backing feature as an actor flag: AVOIDMELEE. - Gez's misc. bugs patch: * Moves the dog sound out of the Doom-specific sounds in SNDINFO to address this, * Renames the dog actor to MBFHelperDog to prevent name conflicts, * Adds APROP_Score to CheckActorProperty, * Completes the randomspawner update (the reason I moved the recursion counter out of special1 was that I found some projectiles had this set to them, for example in A_LichAttack, but I forgot to add transfer for them), * Provides centered sprites for beta plasma balls if this is deemed deserving correction. - Added some pieces of MBF's friendly AI. - Cleaned up A_LookEx code and merged most of it with the base functions. The major difference was a common piece of code that was repeated 5 times throughout the code so I moved it into a subfunction. - Changed P_BlockmapSearch to pass a user parameter to its callback so that A_LookEx does not need to store its info inside the actor itself. - fixed: The linetarget CCMD duplicated all of the info CCMD. - fixed: PrintActorInfo crashed due to some incomplete implementation. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@458 b0f79afe-0144-0410-b225-9a4edf0717df --- docs/rh-log.txt | 24 + gzdoom.vcproj | 4 - src/CMakeLists.txt | 1 - src/actor.h | 11 +- src/b_bot.cpp | 1 - src/b_func.cpp | 2 +- src/b_move.cpp | 2 +- src/c_cmds.cpp | 1 - src/d_dehacked.cpp | 12 +- src/g_doom/a_bossbrain.cpp | 2 +- src/g_doom/a_scriptedmarine.cpp | 2 +- src/g_hexen/a_dragon.cpp | 2 +- src/g_hexen/a_firedemon.cpp | 2 +- src/g_hexen/a_magestaff.cpp | 4 +- src/g_shared/a_pickups.cpp | 5 +- src/g_shared/a_pickups.h | 4 +- src/g_shared/a_randomspawner.cpp | 2 + src/p_acs.cpp | 1 + src/p_enemy.cpp | 505 ++++++++++++--- src/p_enemy.h | 21 +- src/p_enemy_a_lookex.cpp | 904 --------------------------- src/p_interaction.cpp | 16 +- src/p_local.h | 5 +- src/p_maputl.cpp | 16 +- src/p_mobj.cpp | 3 +- src/svnrevision.h | 4 +- src/textures/tgatexture.cpp | 8 +- src/thingdef/thingdef_data.cpp | 3 +- src/thingdef/thingdef_properties.cpp | 6 +- src/version.h | 2 +- wadsrc_bm/brightmaps.vcproj | 2 +- wadsrc_lights/lights.vcproj | 2 +- wadsrc_lights/static/doomdefs.txt | 92 +++ 33 files changed, 598 insertions(+), 1073 deletions(-) delete mode 100644 src/p_enemy_a_lookex.cpp diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 9c064977..bd48ce1c 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,27 @@ +September 16, 2009 (Changes by Graf Zahl) +- Fixed: The deprecated flag handler for the old bounce flags needs to clear + BOUNCE_MBF and BOUNCE_UseSeeSound, too, when clearing one of these flags. +- Fixed: When adding the AVOIDMELEE code the code was accidentally changed so that + friendly monsters could no longer acquire targets by themselves. +- Renamed WIF_BOT_MELEE to WIF_MELEEWEAPON because it's no longer a bot only flag. +- Added MBF's monster_backing feature as an actor flag: AVOIDMELEE. +- Gez's misc. bugs patch: +* Moves the dog sound out of the Doom-specific sounds in SNDINFO to address this, +* Renames the dog actor to MBFHelperDog to prevent name conflicts, +* Adds APROP_Score to CheckActorProperty, +* Completes the randomspawner update (the reason I moved the recursion counter out of + special1 was that I found some projectiles had this set to them, for example in + A_LichAttack, but I forgot to add transfer for them), +* Provides centered sprites for beta plasma balls if this is deemed deserving correction. +- Added some pieces of MBF's friendly AI. +- Cleaned up A_LookEx code and merged most of it with the base functions. + The major difference was a common piece of code that was repeated 5 times + throughout the code so I moved it into a subfunction. +- Changed P_BlockmapSearch to pass a user parameter to its callback so that + A_LookEx does not need to store its info inside the actor itself. +- fixed: The linetarget CCMD duplicated all of the info CCMD. +- fixed: PrintActorInfo crashed due to some incomplete implementation. + September 15, 2009 (Changes by Graf Zahl) - added PinkSilver's A_Respawn enhancement patch. - added RandomSpawner update from Gez's experimental build. diff --git a/gzdoom.vcproj b/gzdoom.vcproj index afc81845..c8484fc5 100644 --- a/gzdoom.vcproj +++ b/gzdoom.vcproj @@ -797,10 +797,6 @@ RelativePath=".\src\p_enemy.cpp" > - - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ca264bdd..c1e1d2d6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -607,7 +607,6 @@ add_executable( zdoom WIN32 p_doors.cpp p_effect.cpp p_enemy.cpp - p_enemy_a_lookex.cpp p_floor.cpp p_interaction.cpp p_lights.cpp diff --git a/src/actor.h b/src/actor.h index 82d1d97e..22e86dc6 100644 --- a/src/actor.h +++ b/src/actor.h @@ -217,7 +217,7 @@ enum MF3_NOBLOCKMONST = 0x00100000, // Can cross ML_BLOCKMONSTERS lines MF3_CRASHED = 0x00200000, // Actor entered its crash state MF3_FULLVOLDEATH = 0x00400000, // DeathSound is played full volume (for missiles) - /* = 0x00800000, */ + MF3_AVOIDMELEE = 0x00800000, // Avoids melee attacks (same as MBF's monster_backing but must be explicitly set) /* = 0x01000000, */ MF3_FOILINVUL = 0x02000000, // Actor can hurt MF2_INVULNERABLE things MF3_NOTELEOTHER = 0x04000000, // Monster is unaffected by teleport other artifact @@ -761,6 +761,7 @@ public: BYTE movedir; // 0-7 SBYTE visdir; SWORD movecount; // when 0, select a new dir + SWORD strafecount; // for MF3_AVOIDMELEE TObjPtr target; // thing being chased/attacked (or NULL) // also the originator for missiles TObjPtr lastenemy; // Last known enemy -- killough 2/15/98 @@ -811,14 +812,6 @@ public: AActor *BlockingMobj; // Actor that blocked the last move line_t *BlockingLine; // Line that blocked the last move - // [KS] These temporary-use properties are needed to allow A_LookEx to pass its parameters to - // LookFor*InBlock in P_BlockmapSearch so that friendly enemies and monsters that look for - // other monsters can find their targets properly. If there's a cleaner way of doing this, - // feel free to remove these and use that method instead. - fixed_t LookExMinDist; // Minimum sight distance - fixed_t LookExMaxDist; // Maximum sight distance - angle_t LookExFOV; // Field of Vision - // a linked list of sectors where this object appears struct msecnode_t *touching_sectorlist; // phares 3/14/98 diff --git a/src/b_bot.cpp b/src/b_bot.cpp index b03c067f..3911264c 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -136,7 +136,6 @@ void InitBotStuff() { "SkullRod", 27000000, 0, "HornRodFX1" }, { "SkullRodPowered", 27000000, 0, "HornRodFX2" }, { "PhoenixRod", 18350080, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "PhoenixFX1" }, - { "PhoenixRodPowered", 0, WIF_BOT_MELEE, "PhoenixFX2" }, { "Mace", 27000000, WIF_BOT_REACTION_SKILL_THING, "MaceFX2" }, { "MacePowered", 27000000, WIF_BOT_REACTION_SKILL_THING|WIF_BOT_EXPLOSIVE, "MaceFX4" }, { "FWeapHammer", 22000000, 0, "HammerMissile" }, diff --git a/src/b_func.cpp b/src/b_func.cpp index 5da2e8e2..adaa755c 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -175,7 +175,7 @@ void FCajunMaster::Dofire (AActor *actor, ticcmd_t *cmd) (actor->y + actor->vely) - (enemy->y + enemy->vely)); //FIRE EACH TYPE OF WEAPON DIFFERENT: Here should all the different weapons go. - if (actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_MELEE) + if (actor->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON) { if ((actor->player->ReadyWeapon->ProjectileType != NULL)) { diff --git a/src/b_move.cpp b/src/b_move.cpp index 896ce934..332160f1 100644 --- a/src/b_move.cpp +++ b/src/b_move.cpp @@ -342,7 +342,7 @@ void FCajunMaster::TurnToAng (AActor *actor) if(actor->player->enemy) if(!actor->player->dest) //happens when running after item in combat situations, or normal, prevents weak turns - if(actor->player->ReadyWeapon->ProjectileType == NULL && !(actor->player->ReadyWeapon->WeaponFlags & WIF_BOT_MELEE)) + if(actor->player->ReadyWeapon->ProjectileType == NULL && !(actor->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON)) if(Check_LOS(actor, actor->player->enemy, SHOOTFOV+5*ANGLE_1)) maxturn = 3; } diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index 3cddb6d5..ed27e2d2 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -778,7 +778,6 @@ CCMD(linetarget) linetarget->GetClass()->TypeName.GetChars(), linetarget->health, linetarget->SpawnHealth()); - PrintMiscActorInfo(linetarget); } else Printf("No target found\n"); } diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index f6397819..1ac3ff28 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -149,10 +149,10 @@ static TArray WeaponNames; // List of states that are hacked to use a codepointer struct MBFParamState { - FState * state; + FState *state; int pointer; }; -static TArray MBFParamStates; +static TArray MBFParamStates; // Data on how to correctly modify the codepointers struct CodePointerAlias { @@ -1610,9 +1610,9 @@ static void SetPointer(FState *state, PSymbol *sym, int frame = 0) { if (!symname.CompareNoCase(MBFCodePointers[i].name)) { - MBFParamState * newstate = new MBFParamState; - newstate->state = state; - newstate->pointer = i; + MBFParamState newstate; + newstate.state = state; + newstate.pointer = i; MBFParamStates.Push(newstate); break; // No need to cycle through the rest of the list. } @@ -2494,7 +2494,7 @@ static void UnloadDehSupp () // Handle MBF params here, before the required arrays are cleared for (unsigned int i=0; i < MBFParamStates.Size(); i++) { - SetDehParams(MBFParamStates[i]->state, MBFParamStates[i]->pointer); + SetDehParams(MBFParamStates[i].state, MBFParamStates[i].pointer); } MBFParamStates.Clear(); MBFParamStates.ShrinkToFit(); diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 2fc203e1..7764f2ec 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -238,7 +238,7 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound) { newmobj->CopyFriendliness (eye, false); } - if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true)) + if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true, NULL)) newmobj->SetState (newmobj->SeeState); if (!(newmobj->ObjectFlags & OF_EuthanizeMe)) diff --git a/src/g_doom/a_scriptedmarine.cpp b/src/g_doom/a_scriptedmarine.cpp index fbae607c..9f6f5405 100644 --- a/src/g_doom/a_scriptedmarine.cpp +++ b/src/g_doom/a_scriptedmarine.cpp @@ -168,7 +168,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_M_Refire) { if (self->MissileState && pr_m_refire() < 160) { // Look for a new target most of the time - if (P_LookForPlayers (self, true) && P_CheckMissileRange (self)) + if (P_LookForPlayers (self, true, NULL) && P_CheckMissileRange (self)) { // Found somebody new and in range, so don't stop shooting return; } diff --git a/src/g_hexen/a_dragon.cpp b/src/g_hexen/a_dragon.cpp index 8ef10e24..0c5ea81b 100644 --- a/src/g_hexen/a_dragon.cpp +++ b/src/g_hexen/a_dragon.cpp @@ -213,7 +213,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DragonFlight) } else { - P_LookForPlayers (self, true); + P_LookForPlayers (self, true, NULL); } } diff --git a/src/g_hexen/a_firedemon.cpp b/src/g_hexen/a_firedemon.cpp index 884a12f2..d0366fdf 100644 --- a/src/g_hexen/a_firedemon.cpp +++ b/src/g_hexen/a_firedemon.cpp @@ -145,7 +145,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FiredChase) if(!self->target || !(self->target->flags&MF_SHOOTABLE)) { // Invalid target - P_LookForPlayers (self,true); + P_LookForPlayers (self,true, NULL); return; } diff --git a/src/g_hexen/a_magestaff.cpp b/src/g_hexen/a_magestaff.cpp index 85b51d33..76610f69 100644 --- a/src/g_hexen/a_magestaff.cpp +++ b/src/g_hexen/a_magestaff.cpp @@ -19,7 +19,7 @@ void A_DropBloodscourgePieces (AActor *); void A_MStaffAttack (AActor *actor); void A_MStaffPalette (AActor *actor); -static AActor *FrontBlockCheck (AActor *mo, int index); +static AActor *FrontBlockCheck (AActor *mo, int index, void *); static divline_t BlockCheckLine; //========================================================================== @@ -254,7 +254,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MStaffTrack) // //============================================================================ -static AActor *FrontBlockCheck (AActor *mo, int index) +static AActor *FrontBlockCheck (AActor *mo, int index, void *) { FBlockNode *link; diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 045e5bf9..e9d9e200 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1741,10 +1741,7 @@ IMPLEMENT_CLASS(AScoreItem) // // AScoreItem :: TryPickup // -// This function does nothing much. Theoretically, the player could have a -// score property which would be incremented by the score items' own score -// property (probably using the Amount property for that), but that is not -// needed for the moment. +// Adds the value (Amount) of the item to the toucher's Score property. // //=========================================================================== diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 6ccc8cd5..b402fcf5 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -322,6 +322,7 @@ enum WIF_NO_AUTO_SWITCH = 0x00001000, // never switch to this weapon when it's picked up WIF_STAFF2_KICKBACK = 0x00002000, // the powered-up Heretic staff has special kickback WIF_NOAUTOAIM = 0x00004000, // this weapon never uses autoaim (useful for ballistic projectiles) + WIF_MELEEWEAPON = 0x00008000, // melee weapon. Used by bots and monster AI. WIF_CHEATNOTWEAPON = 0x08000000, // Give cheat considers this not a weapon (used by Sigil) @@ -329,7 +330,6 @@ enum WIF_BOT_REACTION_SKILL_THING = 1<<31, // I don't understand this WIF_BOT_EXPLOSIVE = 1<<30, // weapon fires an explosive - WIF_BOT_MELEE = 1<<29, // melee weapon WIF_BOT_BFG = 1<<28, // this is a BFG }; @@ -477,7 +477,7 @@ public: // A score item is picked up without being added to the inventory. -// Contrarily to FakeInventory, it does nothing. +// It differs from FakeInventory by doing nothing more than increasing the player's score. class AScoreItem : public AInventory { DECLARE_CLASS (AScoreItem, AInventory) diff --git a/src/g_shared/a_randomspawner.cpp b/src/g_shared/a_randomspawner.cpp index b4b9176a..a5ffa925 100644 --- a/src/g_shared/a_randomspawner.cpp +++ b/src/g_shared/a_randomspawner.cpp @@ -111,6 +111,8 @@ class ARandomSpawner : public AActor newmobj->args[2] = args[2]; newmobj->args[3] = args[3]; newmobj->args[4] = args[4]; + newmobj->special1 = special1; + newmobj->special2 = special2; newmobj->SpawnFlags = SpawnFlags; newmobj->HandleSpawnFlags(); newmobj->tid = tid; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index e45f9275..3f24ad0e 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -2684,6 +2684,7 @@ int DLevelScript::CheckActorProperty (int tid, int property, int value) case APROP_Gravity: case APROP_SpawnHealth: case APROP_JumpZ: + case APROP_Score: return (GetActorProperty(tid, property) == value); // Boolean values need to compare to a binary version of value diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index a321955a..d2a1e1c6 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -62,8 +62,10 @@ static FRandom pr_look2 ("LookyLooky"); static FRandom pr_look3 ("IGotHooky"); static FRandom pr_slook ("SlooK"); static FRandom pr_dropoff ("Dropoff"); +static FRandom pr_defect ("Defect"); static FRandom pr_skiptarget("SkipTarget"); +static FRandom pr_enemystrafe("EnemyStrafe"); // movement interpolation is fine for objects that are moved by their own // velocity. But for monsters it is problematic. @@ -219,20 +221,20 @@ void P_NoiseAlert (AActor *target, AActor *emmiter, bool splash) bool AActor::CheckMeleeRange () { - AActor *pl; + AActor *pl = target; + fixed_t dist; - if (!target) + if (!pl) return false; - pl = target; dist = P_AproxDistance (pl->x - x, pl->y - y); if (dist >= meleerange + pl->radius) return false; // [RH] If moving toward goal, then we've reached it. - if (target == goal) + if (pl == goal) return true; // [RH] Don't melee things too far above or below actor. @@ -243,6 +245,10 @@ bool AActor::CheckMeleeRange () if (pl->z + pl->height < z) return false; } + + // killough 7/18/98: friendly monsters don't attack other friends + if (IsFriend(pl)) + return false; if (!P_CheckSight (this, pl, 0)) return false; @@ -279,6 +285,12 @@ bool P_CheckMeleeRange2 (AActor *actor) { // Attacker is higher return false; } + else if (actor->IsFriend(mo)) + { + // killough 7/18/98: friendly monsters don't attack other friends + return false; + } + if (!P_CheckSight(actor, mo)) { return false; @@ -303,12 +315,34 @@ bool P_CheckMissileRange (AActor *actor) { // the target just hit the enemy, so fight back! actor->flags &= ~MF_JUSTHIT; - return true; + + // killough 7/18/98: no friendly fire at corpses + // killough 11/98: prevent too much infighting among friends + // Cleaned up and made readable + if (!(actor->flags & MF_FRIENDLY)) return true; + if (actor->target->health <= 0) return false; + if (!actor->IsFriend(actor->target)) return true; + if (actor->target->player != NULL) + { + return (pr_defect() >128); + } + else + { + return !(actor->target->flags & MF_JUSTHIT) && pr_defect() >128; + } } if (actor->reactiontime) return false; // do not attack yet - + + // killough 7/18/98: friendly monsters don't attack other friendly + // monsters or players (except when attacked, and then only once) + if (actor->IsFriend(actor->target)) + return false; + + if (actor->flags & MF_FRIENDLY && P_HitFriend(actor)) + return false; + // OPTIMIZE: get this from a global checksight // [RH] What? dist = P_AproxDistance (actor->x-actor->target->x, @@ -357,7 +391,7 @@ bool P_HitFriend(AActor * self) if (self->flags&MF_FRIENDLY && self->target != NULL) { angle_t angle = R_PointToAngle2 (self->x, self->y, self->target->x, self->target->y); - fixed_t dist = P_AproxDistance (self->x-self->target->x, self->y-self->target->y); + fixed_t dist = P_AproxDistance (self->x - self->target->x, self->y - self->target->y); P_AimLineAttack (self, angle, dist, &linetarget, 0, true); if (linetarget != NULL && linetarget != self->target) { @@ -739,6 +773,8 @@ void P_NewChaseDir(AActor * actor) fixed_t deltax; fixed_t deltay; + actor->strafecount = 0; + if ((actor->flags5&MF5_CHASEGOAL || actor->goal == actor->target) && actor->goal!=NULL) { deltax = actor->goal->x - actor->x; @@ -831,7 +867,56 @@ void P_NewChaseDir(AActor * actor) return; } } + +#if 0 + // Move away from friends when too close, except + // in certain situations (e.g. a crowded lift) + + // MBF code for friends. Cannot be done in ZDoom but left here as a reminder for later implementation. + + if (actor->flags & target->flags & MF_FRIEND && + distfriend << FRACBITS > dist && + !P_IsOnLift(target) && !P_IsUnderDamage(actor)) + deltax = -deltax, deltay = -deltay; + else +#endif + + // MBF's monster_backing option. Made an actor flag instead. Also cleaned the code up to make it readable. + // Todo: implement the movement logic + AActor *target = actor->target; + if (target->health > 0 && !actor->IsFriend(target)) + { // Live enemy target + + if (actor->flags3 & MF3_AVOIDMELEE) + { + bool ismeleeattacker = false; + fixed_t dist = P_AproxDistance(actor->x-target->x, actor->y-target->y); + if (target->player == NULL) + { + ismeleeattacker = (target->MissileState == NULL && dist < (target->meleerange + target->radius)*2); + } + else if (target->player->ReadyWeapon != NULL) + { + // melee range of player weapon is a parameter of the action function and cannot be checked here. + // Add a new weapon property? + ismeleeattacker = (target->player->ReadyWeapon->WeaponFlags & WIF_MELEEWEAPON && dist < MELEERANGE*3); + } + if (ismeleeattacker) + { + actor->strafecount = pr_enemystrafe() & 15; + deltax = -deltax, deltay = -deltay; + } + } + } + P_DoNewChaseDir(actor, deltax, deltay); + + // If strafing, set movecount to strafecount so that old Doom + // logic still works the same, except in the strafing part + + if (actor->strafecount) + actor->movecount = actor->strafecount; + } @@ -996,6 +1081,58 @@ void P_RandomChaseDir (AActor *actor) actor->movedir = DI_NODIR; // cannot move } +//--------------------------------------------------------------------------- +// +// P_IsVisible +// +// killough 9/9/98: whether a target is visible to a monster +// Extended to handle all A_LookEx related checking, too. +// +//--------------------------------------------------------------------------- + +bool P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams *params) +{ + fixed_t maxdist; + fixed_t mindist; + angle_t fov; + + if (params != NULL) + { + maxdist = params->maxdist; + mindist = params->mindist; + fov = params->fov; + } + else + { + mindist = maxdist = 0; + fov = allaround? 0 : ANGLE_180; + } + + fixed_t dist = P_AproxDistance (other->x - lookee->x, other->y - lookee->y); + + if (maxdist && dist > maxdist) + return false; // [KS] too far + + if (mindist && dist < mindist) + return false; // [KS] too close + + if (fov && fov < ANGLE_MAX) + { + angle_t an = R_PointToAngle2 (lookee->x, lookee->y, other->x, other->y) - lookee->angle; + + if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) + { + // if real close, react anyway + // [KS] but respect minimum distance rules + if (mindist || dist > MELEERANGE) + return false; // outside of fov + } + } + + // P_CheckSight is by far the most expensive operation in here so let's do it last. + return P_CheckSight(lookee, other, 2); +} + //--------------------------------------------------------------------------- // // FUNC P_LookForMonsters @@ -1061,8 +1198,9 @@ bool P_LookForMonsters (AActor *actor) // //============================================================================ -AActor *LookForTIDinBlock (AActor *lookee, int index) +AActor *LookForTIDInBlock (AActor *lookee, int index, void *extparams) { + FLookExParams *params = (FLookExParams *)extparams; FBlockNode *block; AActor *link; AActor *other; @@ -1104,25 +1242,8 @@ AActor *LookForTIDinBlock (AActor *lookee, int index) if (!(lookee->flags3 & MF3_NOSIGHTCHECK)) { - if (!P_CheckSight (lookee, other, 2)) + if (!P_IsVisible(lookee, other, true, params)) continue; // out of sight - /* - if (!allaround) - { - angle_t an = R_PointToAngle2 (actor->x, actor->y, - other->x, other->y) - - actor->angle; - - if (an > ANG90 && an < ANG270) - { - fixed_t dist = P_AproxDistance (other->x - actor->x, - other->y - actor->y); - // if real close, react anyway - if (dist > MELEERANGE) - continue; // behind back - } - } - */ } return other; @@ -1138,12 +1259,13 @@ AActor *LookForTIDinBlock (AActor *lookee, int index) // //============================================================================ -bool P_LookForTID (AActor *actor, INTBOOL allaround) +bool P_LookForTID (AActor *actor, INTBOOL allaround, FLookExParams *params) { AActor *other; bool reachedend = false; + bool chasegoal = params? (!(params->flags & LOF_DONTCHASEGOAL)) : true; - other = P_BlockmapSearch (actor, 0, LookForTIDinBlock); + other = P_BlockmapSearch (actor, 0, LookForTIDInBlock, params); if (other != NULL) { @@ -1198,24 +1320,8 @@ bool P_LookForTID (AActor *actor, INTBOOL allaround) if (!(actor->flags3 & MF3_NOSIGHTCHECK)) { - if (!P_CheckSight (actor, other, 2)) + if (!P_IsVisible (actor, other, !!allaround, params)) continue; // out of sight - - if (!allaround) - { - angle_t an = R_PointToAngle2 (actor->x, actor->y, - other->x, other->y) - - actor->angle; - - if (an > ANG90 && an < ANG270) - { - fixed_t dist = P_AproxDistance (other->x - actor->x, - other->y - actor->y); - // if real close, react anyway - if (dist > MELEERANGE) - continue; // behind back - } - } } // [RH] Need to be sure the reactiontime is 0 if the monster is @@ -1231,7 +1337,7 @@ bool P_LookForTID (AActor *actor, INTBOOL allaround) if (actor->target == NULL) { // [RH] use goal as target - if (actor->goal != NULL) + if (actor->goal != NULL && chasegoal) { actor->target = actor->goal; return true; @@ -1256,18 +1362,19 @@ bool P_LookForTID (AActor *actor, INTBOOL allaround) //============================================================================ // -// LookForTIDinBlock +// LookForEnemiesinBlock // // Finds a non-friendly monster in a mapblock. It can also use targets of // friendlies in this mapblock to find non-friendlies in other mapblocks. // //============================================================================ -AActor *LookForEnemiesInBlock (AActor *lookee, int index) +AActor *LookForEnemiesInBlock (AActor *lookee, int index, void *extparam) { FBlockNode *block; AActor *link; AActor *other; + FLookExParams *params = (FLookExParams *)extparam; for (block = blocklinks[index]; block != NULL; block = block->NextActor) { @@ -1330,25 +1437,11 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index) } } - if (other == NULL || !P_CheckSight (lookee, other, 2)) + // [KS] Hey, shouldn't there be a check for MF3_NOSIGHTCHECK here? + + if (other == NULL || !P_IsVisible (lookee, other, true, params)) continue; // out of sight - /* - if (!allaround) - { - angle_t an = R_PointToAngle2 (actor->x, actor->y, - other->x, other->y) - - actor->angle; - - if (an > ANG90 && an < ANG270) - { - fixed_t dist = P_AproxDistance (other->x - actor->x, - other->y - actor->y); - // if real close, react anyway - if (dist > MELEERANGE) - continue; // behind back - } - } - */ + return other; } @@ -1363,11 +1456,11 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index) // //============================================================================ -bool P_LookForEnemies (AActor *actor, INTBOOL allaround) +bool P_LookForEnemies (AActor *actor, INTBOOL allaround, FLookExParams *params) { AActor *other; - other = P_BlockmapSearch (actor, 10, LookForEnemiesInBlock); + other = P_BlockmapSearch (actor, 10, LookForEnemiesInBlock, params); if (other != NULL) { @@ -1415,18 +1508,17 @@ bool P_LookForEnemies (AActor *actor, INTBOOL allaround) ================ */ -bool P_LookForPlayers (AActor *actor, INTBOOL allaround) +bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) { int c; int stop; int pnum; player_t* player; - angle_t an; - fixed_t dist; + bool chasegoal = params? (!(params->flags & LOF_DONTCHASEGOAL)) : true; if (actor->TIDtoHate != 0) { - if (P_LookForTID (actor, allaround)) + if (P_LookForTID (actor, allaround, params)) { return true; } @@ -1437,10 +1529,43 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround) } else if (actor->flags & MF_FRIENDLY) { - if (!deathmatch) // [SP] If you don't see any enemies in deathmatch, look for players. - return P_LookForEnemies (actor, allaround); - else if ( P_LookForEnemies (actor, allaround) ) - return true; + bool result = P_LookForEnemies (actor, allaround, params); + +#ifdef MBF_FRIENDS + if (!result && (actor->flags & MF_FRIEND_MBF)) + { // killough 9/9/98: friendly monsters go about players differently + + // Go back to a player, no matter whether it's visible or not + for (int anyone=0; anyone<=1; anyone++) + { + for (int c=0; cIsFriend(players[c].mo) && + (anyone || P_IsVisible(actor, players[c].mo, allaround))) + { + actor->target = players[c].mo; + + // killough 12/98: + // get out of refiring loop, to avoid hitting player accidentally + + if (actor->MissileState != NULL) + { + actor->SetStateNF(actor->SeeState); + actor->flags &= ~MF_JUSTHIT; + } + + return true; + } + } + } + } +#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 (result || !deathmatch) return true; + + } // [SP] if false, and in deathmatch, intentional fall-through if (!(gameinfo.gametype & (GAME_DoomStrifeChex)) && @@ -1478,7 +1603,8 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround) if (actor->target == NULL) { // [RH] use goal as target - if (actor->goal != NULL) + // [KS] ...unless we're ignoring goals and we don't already have one + if (actor->goal != NULL && chasegoal) { actor->target = actor->goal; return true; @@ -1512,7 +1638,7 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround) if (player->health <= 0) continue; // dead - if (!P_CheckSight (actor, player->mo, 2)) + if (!P_IsVisible (actor, player->mo, allaround, params)) continue; // out of sight // [SP] Deathmatch fixes - if we have MF_FRIENDLY we're definitely in deathmatch @@ -1525,23 +1651,6 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround) continue; // This is my master. } - if (!allaround) - { - an = R_PointToAngle2 (actor->x, - actor->y, - player->mo->x, - player->mo->y) - - actor->angle; - - if (an > ANG90 && an < ANG270) - { - dist = P_AproxDistance (player->mo->x - actor->x, - player->mo->y - actor->y); - // if real close, react anyway - if (dist > MELEERANGE) - continue; // behind back - } - } if ((player->mo->flags & MF_SHADOW && !(i_compatflags & COMPATF_INVISIBILITY)) || player->mo->flags3 & MF3_GHOST) { @@ -1630,7 +1739,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) { // If we find a valid target here, the wandering logic should *not* // be activated! It would cause the seestate to be set twice. - if (P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND)) + if (P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND, NULL)) goto seeyou; // Let the self wander around aimlessly looking for a fight @@ -1657,7 +1766,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) } } - if (!P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND)) + if (!P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND, NULL)) return; // go into chase state @@ -1687,6 +1796,193 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look) } +//========================================================================== +// +// A_LookEx (int flags, fixed minseedist, fixed maxseedist, fixed maxheardist, fixed fov, state wakestate) +// [KS] Borrowed the A_Look code to make a parameterized version. +// +//========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx) +{ + ACTION_PARAM_START(6); + ACTION_PARAM_INT(flags, 0); + ACTION_PARAM_FIXED(minseedist, 1); + ACTION_PARAM_FIXED(maxseedist, 2); + ACTION_PARAM_FIXED(maxheardist, 3); + ACTION_PARAM_ANGLE(fov, 4); + ACTION_PARAM_STATE(seestate, 5); + + AActor *targ = NULL; // Shuts up gcc + fixed_t dist; + FLookExParams params = {fov, minseedist, maxseedist, maxheardist, flags, seestate }; + + if (self->flags5 & MF5_INCONVERSATION) + return; + + // [RH] Set goal now if appropriate + if (self->special == Thing_SetGoal && self->args[0] == 0) + { + NActorIterator iterator (NAME_PatrolPoint, self->args[1]); + self->special = 0; + self->goal = iterator.Next (); + self->reactiontime = self->args[2] * TICRATE + level.maptime; + if (self->args[3] == 0) self->flags5 &=~ MF5_CHASEGOAL; + else self->flags5 |= MF5_CHASEGOAL; + } + + self->threshold = 0; // any shot will wake up + + if (self->TIDtoHate != 0) + { + targ = self->target; + } + else + { + if (!(flags & LOF_NOSOUNDCHECK)) + { + targ = self->LastHeard; + if (targ != NULL) + { + // [RH] If the soundtarget is dead, don't chase it + if (targ->health <= 0) + { + targ = NULL; + } + else + { + dist = P_AproxDistance (targ->x - self->x, + targ->y - self->y); + + // [KS] If the target is too far away, don't respond to the sound. + if (maxheardist && dist > maxheardist) + { + targ = NULL; + self->LastHeard = NULL; + } + } + } + } + + if (targ && targ->player && (targ->player->cheats & CF_NOTARGET)) + { + return; + } + } + + // [RH] Andy Baker's stealth monsters + if (self->flags & MF_STEALTH) + { + self->visdir = -1; + } + + if (targ && (targ->flags & MF_SHOOTABLE)) + { + if (self->IsFriend (targ)) // be a little more precise! + { + if (!(self->flags4 & MF4_STANDSTILL)) + { + if (!(flags & LOF_NOSIGHTCHECK)) + { + // If we find a valid target here, the wandering logic should *not* + // be activated! If would cause the seestate to be set twice. + if (P_LookForPlayers(self, true, ¶ms)) + goto seeyou; + } + + // Let the self wander around aimlessly looking for a fight + if (!(self->flags & MF_INCHASE)) + { + if (seestate) + { + self->SetState (seestate); + } + else + { + if (self->SeeState != NULL) + { + self->SetState (self->SeeState); + } + else + { + CALL_ACTION(A_Wander, self); + } + } + } + } + } + else + { + self->target = targ; //We already have a target? + + // [KS] The target can become ourselves in rare circumstances (like + // if we committed suicide), so if that's the case, just ignore it. + if (self->target == self) self->target = NULL; + + if (self->target != NULL) + { + if (self->flags & MF_AMBUSH) + { + dist = P_AproxDistance (self->target->x - self->x, + self->target->y - self->y); + if (P_CheckSight (self, self->target, 2) && + (!minseedist || dist > minseedist) && + (!maxseedist || dist < maxseedist)) + { + goto seeyou; + } + } + else + goto seeyou; + } + } + } + + if (!(flags & LOF_NOSIGHTCHECK)) + { + if (!P_LookForPlayers(self, true, ¶ms)) + return; + } + else + { + return; + } + + // go into chase state + seeyou: + // [RH] Don't start chasing after a goal if it isn't time yet. + if (self->target == self->goal) + { + if (self->reactiontime > level.maptime) + self->target = NULL; + } + else if (self->SeeSound && !(flags & LOF_NOSEESOUND)) + { + if (flags & LOF_FULLVOLSEESOUND) + { // full volume + S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NONE); + } + else + { + S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NORM); + } + } + + if (self->target && !(self->flags & MF_INCHASE)) + { + if (seestate) + { + self->SetState (seestate); + } + else + { + self->SetState (self->SeeState); + } + } +} + +// [KS] *** End additions by me *** + //========================================================================== // // A_Wander @@ -1770,7 +2066,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look2) } else { - if (!P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND)) + if (!P_LookForPlayers (self, self->flags4 & MF4_LOOKALLAROUND, NULL)) goto nosee; self->SetState (self->SeeState); self->flags4 |= MF4_INCOMBAT; @@ -1856,7 +2152,11 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi } // turn towards movement direction if not there yet - if (actor->movedir < 8) + if (actor->strafecount) + { + A_FaceTarget(actor); + } + else if (actor->movedir < 8) { actor->angle &= (angle_t)(7<<29); delta = actor->angle - (actor->movedir << 29); @@ -1916,7 +2216,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi // hurt our old one temporarily. actor->threshold = 0; } - if (P_LookForPlayers (actor, true) && actor->target != actor->goal) + if (P_LookForPlayers (actor, true, NULL) && actor->target != actor->goal) { // got a new target actor->flags &= ~MF_INCHASE; return; @@ -2088,7 +2388,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi lookForBetter = true; } AActor * oldtarget = actor->target; - gotNew = P_LookForPlayers (actor, true); + gotNew = P_LookForPlayers (actor, true, NULL); if (lookForBetter) { actor->flags3 |= MF3_NOSIGHTCHECK; @@ -2104,6 +2404,9 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi // chase towards player // + if (actor->strafecount) + actor->strafecount--; + // class bosses don't do this when strafing if ((!fastchase || !actor->FastChaseStrafeCount) && !dontmove) { diff --git a/src/p_enemy.h b/src/p_enemy.h index f111f9d0..ae259806 100644 --- a/src/p_enemy.h +++ b/src/p_enemy.h @@ -25,6 +25,25 @@ enum dirtype_t extern fixed_t xspeed[8], yspeed[8]; +enum LO_Flags +{ + LOF_NOSIGHTCHECK = 1, + LOF_NOSOUNDCHECK = 2, + LOF_DONTCHASEGOAL = 4, + LOF_NOSEESOUND = 8, + LOF_FULLVOLSEESOUND = 16, +}; + +struct FLookExParams +{ + angle_t fov; + fixed_t mindist; + fixed_t maxdist; + fixed_t maxheardist; + int flags; + FState *seestate; +}; + void P_RecursiveSound (sector_t *sec, AActor *soundtarget, bool splash, int soundblocks); bool P_HitFriend (AActor *self); void P_NoiseAlert (AActor *target, AActor *emmiter, bool splash=false); @@ -32,9 +51,9 @@ bool P_CheckMeleeRange2 (AActor *actor); bool P_Move (AActor *actor); bool P_TryWalk (AActor *actor); void P_NewChaseDir (AActor *actor); -bool P_LookForPlayers (AActor *actor, INTBOOL allaround); AInventory *P_DropItem (AActor *source, const PClass *type, int special, int chance); void P_TossItem (AActor *item); +bool P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params); DECLARE_ACTION(A_Look) DECLARE_ACTION(A_Wander) diff --git a/src/p_enemy_a_lookex.cpp b/src/p_enemy_a_lookex.cpp deleted file mode 100644 index 4c68fcbf..00000000 --- a/src/p_enemy_a_lookex.cpp +++ /dev/null @@ -1,904 +0,0 @@ -#include - -#include "templates.h" -#include "m_random.h" -#include "i_system.h" -#include "doomdef.h" -#include "p_local.h" -#include "p_lnspec.h" -#include "s_sound.h" -#include "g_game.h" -#include "doomstat.h" -#include "r_state.h" -#include "c_cvars.h" -#include "p_enemy.h" -#include "a_sharedglobal.h" -#include "a_action.h" -#include "thingdef/thingdef.h" -#include "g_level.h" - -#include "gi.h" - -bool P_LookForMonsters (AActor *actor); - -static FRandom pr_look2 ("LookyLookyEx"); -static FRandom pr_look3 ("IGotHookyEx"); -static FRandom pr_lookforplayers ("LookForPlayersEx"); -static FRandom pr_skiptarget("SkipTargetEx"); - - -// [KS] *** Start additions by me - p_enemy.cpp *** - -// LookForTIDinBlockEx -// LookForEnemiesInBlockEx -// P_NewLookTID (copied from P_LookForTID) -// P_NewLookPlayers (copied from P_LookForPlayers) -// Takes FOV and sight distances into account when acquiring a target. -// TODO: Not sure if using actor properties to pass parameters around indirectly is such a good idea. If there's a cleaner method, do it that way instead. -// ~Kate S. Last updated on 12/23/2007 - -AActor *LookForTIDinBlockEx (AActor *lookee, int index) -{ - FBlockNode *block; - AActor *link; - AActor *other; - fixed_t dist; - angle_t an; - - for (block = blocklinks[index]; block != NULL; block = block->NextActor) - { - link = block->Me; - - if (!(link->flags & MF_SHOOTABLE)) - continue; // not shootable (observer or dead) - - if (link == lookee) - continue; - - if (link->health <= 0) - continue; // dead - - if (link->flags2 & MF2_DORMANT) - continue; // don't target dormant things - - if (link->tid == lookee->TIDtoHate) - { - other = link; - } - else if (link->target != NULL && link->target->tid == lookee->TIDtoHate) - { - other = link->target; - if (!(other->flags & MF_SHOOTABLE) || - other->health <= 0 || - (other->flags2 & MF2_DORMANT)) - { - continue; - } - } - else - { - continue; - } - - if (!(lookee->flags3 & MF3_NOSIGHTCHECK)) - { - if (!P_CheckSight (lookee, other, 2)) - continue; // out of sight - - dist = P_AproxDistance (other->x - lookee->x, - other->y - lookee->y); - - if (lookee->LookExMaxDist && dist > lookee->LookExMaxDist) - continue; // [KS] too far - - if (lookee->LookExMinDist && dist < lookee->LookExMinDist) - continue; // [KS] too close - - if (lookee->LookExFOV && lookee->LookExFOV < ANGLE_MAX) - { - an = R_PointToAngle2 (lookee->x, - lookee->y, - other->x, - other->y) - - lookee->angle; - - if (an > (lookee->LookExFOV / 2) && an < (ANGLE_MAX - (lookee->LookExFOV / 2))) - { - // if real close, react anyway - // [KS] but respect minimum distance rules - if (lookee->LookExMinDist || dist > MELEERANGE) - continue; // outside of fov - } - } - else - { - if(!(lookee->flags4 & MF4_LOOKALLAROUND) || (lookee->LookExFOV >= ANGLE_MAX)) // Just in case angle_t doesn't clamp stuff, because I can't be too sure. - { - an = R_PointToAngle2 (lookee->x, - lookee->y, - other->x, - other->y) - - lookee->angle; - - if (an > ANG90 && an < ANG270) - { - // if real close, react anyway - // [KS] but respect minimum distance rules - if (lookee->LookExMinDist || dist > MELEERANGE) - continue; // behind back - } - } - } - } - - return other; - } - return NULL; -} - -AActor *LookForEnemiesInBlockEx (AActor *lookee, int index) -{ - FBlockNode *block; - AActor *link; - AActor *other; - fixed_t dist; - angle_t an; - - for (block = blocklinks[index]; block != NULL; block = block->NextActor) - { - link = block->Me; - - if (!(link->flags & MF_SHOOTABLE)) - continue; // not shootable (observer or dead) - - if (link == lookee) - continue; - - if (link->health <= 0) - continue; // dead - - if (link->flags2 & MF2_DORMANT) - continue; // don't target dormant things - - if (!(link->flags3 & MF3_ISMONSTER)) - continue; // don't target it if it isn't a monster (could be a barrel) - - other = NULL; - if (link->flags & MF_FRIENDLY) - { - if (deathmatch && - lookee->FriendPlayer != 0 && link->FriendPlayer != 0 && - lookee->FriendPlayer != link->FriendPlayer) - { - // This is somebody else's friend, so go after it - other = link; - } - else if (link->target != NULL && !(link->target->flags & MF_FRIENDLY)) - { - other = link->target; - if (!(other->flags & MF_SHOOTABLE) || - other->health <= 0 || - (other->flags2 & MF2_DORMANT)) - { - other = NULL;; - } - } - } - else - { - other = link; - } - - // [MBF] If the monster is already engaged in a one-on-one attack - // with a healthy friend, don't attack around 60% the time. - - // [GrafZahl] This prevents friendlies from attacking all the same - // target. - - if (other) - { - AActor *targ = other->target; - if (targ && targ->target == other && pr_skiptarget() > 100 && lookee->IsFriend (targ) && - targ->health*2 >= targ->SpawnHealth()) - { - continue; - } - } - - // [KS] Hey, shouldn't there be a check for MF3_NOSIGHTCHECK here? - - if (other == NULL || !P_CheckSight (lookee, other, 2)) - continue; // out of sight - - dist = P_AproxDistance (other->x - lookee->x, - other->y - lookee->y); - - if (lookee->LookExMaxDist && dist > lookee->LookExMaxDist) - continue; // [KS] too far - - if (lookee->LookExMinDist && dist < lookee->LookExMinDist) - continue; // [KS] too close - - if (lookee->LookExFOV && lookee->LookExFOV < ANGLE_MAX) - { - an = R_PointToAngle2 (lookee->x, - lookee->y, - other->x, - other->y) - - lookee->angle; - - if (an > (lookee->LookExFOV / 2) && an < (ANGLE_MAX - (lookee->LookExFOV / 2))) - { - // if real close, react anyway - // [KS] but respect minimum distance rules - if (lookee->LookExMinDist || dist > MELEERANGE) - continue; // outside of fov - } - } - else - { - if(!(lookee->flags4 & MF4_LOOKALLAROUND) || (lookee->LookExFOV >= ANGLE_MAX)) // Just in case angle_t doesn't clamp stuff, because I can't be too sure. - { - an = R_PointToAngle2 (lookee->x, - lookee->y, - other->x, - other->y) - - lookee->angle; - - if (an > ANG90 && an < ANG270) - { - // if real close, react anyway - // [KS] but respect minimum distance rules - if (lookee->LookExMinDist || dist > MELEERANGE) - continue; // behind back - } - } - } - - return other; - } - return NULL; -} - -bool P_NewLookTID (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist, bool chasegoal) -{ - AActor *other; - - actor->LookExMinDist = mindist; - actor->LookExMaxDist = maxdist; - actor->LookExFOV = fov; - other = P_BlockmapSearch (actor, 0, LookForTIDinBlockEx); - - bool reachedend = false; - fixed_t dist; - angle_t an; - - if (other != NULL) - { - if (!(actor->flags3 & MF3_NOSIGHTCHECK)) - { - dist = P_AproxDistance (other->x - actor->x, - other->y - actor->y); - - if (maxdist && dist > maxdist) - { - other = NULL; // [KS] too far - goto endcheck; - } - - if (mindist && dist < mindist) - { - other = NULL; // [KS] too close - goto endcheck; - } - - if (fov && fov < ANGLE_MAX) - { - an = R_PointToAngle2 (actor->x, - actor->y, - other->x, - other->y) - - actor->angle; - - if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) - { - // if real close, react anyway - // [KS] but respect minimum distance rules - if (mindist || dist > MELEERANGE) - { - other = NULL; // outside of fov - goto endcheck; - } - } - } - else - { - if(!((actor->flags4 & MF4_LOOKALLAROUND) || (fov >= ANGLE_MAX))) // Just in case angle_t doesn't clamp stuff, because I can't be too sure. - { - an = R_PointToAngle2 (actor->x, - actor->y, - other->x, - other->y) - - actor->angle; - - if (an > ANG90 && an < ANG270) - { - // if real close, react anyway - // [KS] but respect minimum distance rules - if (mindist || dist > MELEERANGE) - { - other = NULL; // behind back - goto endcheck; - } - } - } - } - } - } - - endcheck: - - if (other != NULL) - { - if (actor->goal && actor->target == actor->goal) - actor->reactiontime = 0; - - actor->target = other; - actor->LastLookActor = other; - return true; - } - - // The actor's TID could change because of death or because of - // Thing_ChangeTID. If it's not what we expect, then don't use - // it as a base for the iterator. - if (actor->LastLookActor != NULL && - actor->LastLookActor->tid != actor->TIDtoHate) - { - actor->LastLookActor = NULL; - } - - FActorIterator iterator (actor->TIDtoHate, actor->LastLookActor); - int c = (pr_look3() & 31) + 7; // Look for between 7 and 38 hatees at a time - while ((other = iterator.Next()) != actor->LastLookActor) - { - if (other == NULL) - { - if (reachedend) - { - // we have cycled through the entire list at least once - // so let's abort because even if we continue nothing can - // be found. - break; - } - reachedend = true; - continue; - } - - if (!(other->flags & MF_SHOOTABLE)) - continue; // not shootable (observer or dead) - - if (other == actor) - continue; // don't hate self - - if (other->health <= 0) - continue; // dead - - if (other->flags2 & MF2_DORMANT) - continue; // don't target dormant things - - if (--c == 0) - break; - - if (!(actor->flags3 & MF3_NOSIGHTCHECK)) - { - if (!P_CheckSight (actor, other, 2)) - continue; // out of sight - - dist = P_AproxDistance (other->x - actor->x, - other->y - actor->y); - - if (maxdist && dist > maxdist) - continue; // [KS] too far - - if (mindist && dist < mindist) - continue; // [KS] too close - - if (fov && fov < ANGLE_MAX) - { - an = R_PointToAngle2 (actor->x, - actor->y, - other->x, - other->y) - - actor->angle; - - if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) - { - // if real close, react anyway - // [KS] but respect minimum distance rules - if (mindist || dist > MELEERANGE) - continue; // outside of fov - } - } - else - { - if(!((actor->flags4 & MF4_LOOKALLAROUND) || (fov >= ANGLE_MAX))) // Just in case angle_t doesn't clamp stuff, because I can't be too sure. - { - an = R_PointToAngle2 (actor->x, - actor->y, - other->x, - other->y) - - actor->angle; - - if (an > ANG90 && an < ANG270) - { - // if real close, react anyway - // [KS] but respect minimum distance rules - if (mindist || dist > MELEERANGE) - continue; // behind back - } - } - } - } - - // [RH] Need to be sure the reactiontime is 0 if the monster is - // leaving its goal to go after something else. - if (actor->goal && actor->target == actor->goal) - actor->reactiontime = 0; - - actor->target = other; - actor->LastLookActor = other; - return true; - } - actor->LastLookActor = other; - if (actor->target == NULL) - { - // [RH] use goal as target - if (actor->goal != NULL && chasegoal) - { - actor->target = actor->goal; - return true; - } - // Use last known enemy if no hatee sighted -- killough 2/15/98: - if (actor->lastenemy != NULL && actor->lastenemy->health > 0) - { - if (!actor->IsFriend(actor->lastenemy)) - { - actor->target = actor->lastenemy; - actor->lastenemy = NULL; - return true; - } - else - { - actor->lastenemy = NULL; - } - } - } - return false; -} - -bool P_NewLookEnemies (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist, bool chasegoal) -{ - AActor *other; - - actor->LookExMinDist = mindist; - actor->LookExMaxDist = maxdist; - actor->LookExFOV = fov; - other = P_BlockmapSearch (actor, 10, LookForEnemiesInBlockEx); - - if (other != NULL) - { - if (actor->goal && actor->target == actor->goal) - actor->reactiontime = 0; - - actor->target = other; -// actor->LastLook.Actor = other; - return true; - } - - if (actor->target == NULL) - { - // [RH] use goal as target - if (actor->goal != NULL) - { - actor->target = actor->goal; - return true; - } - // Use last known enemy if no hatee sighted -- killough 2/15/98: - if (actor->lastenemy != NULL && actor->lastenemy->health > 0) - { - if (!actor->IsFriend(actor->lastenemy)) - { - actor->target = actor->lastenemy; - actor->lastenemy = NULL; - return true; - } - else - { - actor->lastenemy = NULL; - } - } - } - return false; -} - -bool P_NewLookPlayers (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist, bool chasegoal) -{ - int c; - int stop; - int pnum; - player_t* player; - angle_t an; - fixed_t dist; - - if (actor->TIDtoHate != 0) - { - if (P_NewLookTID (actor, fov, mindist, maxdist, chasegoal)) - { - return true; - } - if (!(actor->flags3 & MF3_HUNTPLAYERS)) - { - return false; - } - } - else if (actor->flags & MF_FRIENDLY) - { - if (!deathmatch) // [SP] If you don't see any enemies in deathmatch, look for players. - return P_NewLookEnemies (actor, fov, mindist, maxdist, chasegoal); - else if ( P_NewLookEnemies (actor, fov, mindist, maxdist, chasegoal) ) - return true; - } // [SP] if false, and in deathmatch, intentional fall-through - - if (!(gameinfo.gametype & (GAME_DoomStrifeChex)) && - !multiplayer && - players[0].health <= 0) - { // Single player game and player is dead; look for monsters - return P_LookForMonsters (actor); - } - - c = 0; - if (actor->TIDtoHate != 0) - { - pnum = pr_look2() & (MAXPLAYERS-1); - } - else - { - pnum = actor->LastLookPlayerNumber; - } - stop = (pnum - 1) & (MAXPLAYERS-1); - - for (;;) - { - pnum = (pnum + 1) & (MAXPLAYERS-1); - if (!playeringame[pnum]) - continue; - - if (actor->TIDtoHate == 0) - { - actor->LastLookPlayerNumber = pnum; - } - - if (++c == MAXPLAYERS-1 || pnum == stop) - { - // done looking - if (actor->target == NULL) - { - // [RH] use goal as target - // [KS] ...unless we're ignoring goals and we don't already have one - if (actor->goal != NULL && chasegoal) - { - actor->target = actor->goal; - return true; - } - // Use last known enemy if no players sighted -- killough 2/15/98: - if (actor->lastenemy != NULL && actor->lastenemy->health > 0) - { - if (!actor->IsFriend(actor->lastenemy)) - { - actor->target = actor->lastenemy; - actor->lastenemy = NULL; - return true; - } - else - { - actor->lastenemy = NULL; - } - } - } - return actor->target == actor->goal && actor->goal != NULL; - } - - player = &players[pnum]; - - if (!(player->mo->flags & MF_SHOOTABLE)) - continue; // not shootable (observer or dead) - - if (player->cheats & CF_NOTARGET) - continue; // no target - - if (player->health <= 0) - continue; // dead - - if (!P_CheckSight (actor, player->mo, 2)) - continue; // out of sight - - dist = P_AproxDistance (player->mo->x - actor->x, - player->mo->y - actor->y); - - if (maxdist && dist > maxdist) - continue; // [KS] too far - - if (mindist && dist < mindist) - continue; // [KS] too close - - // [SP] Deathmatch fixes - if we have MF_FRIENDLY we're definitely in deathmatch - // 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 (fov) - { - an = R_PointToAngle2 (actor->x, - actor->y, - player->mo->x, - player->mo->y) - - actor->angle; - - if (an > (fov / 2) && an < (ANGLE_MAX - (fov / 2))) - { - // if real close, react anyway - // [KS] but respect minimum distance rules - if (mindist || dist > MELEERANGE) - continue; // outside of fov - } - } - else - { - if(!((actor->flags4 & MF4_LOOKALLAROUND) || (fov >= ANGLE_MAX))) - { - an = R_PointToAngle2 (actor->x, - actor->y, - player->mo->x, - player->mo->y) - - actor->angle; - - if (an > ANG90 && an < ANG270) - { - // if real close, react anyway - // [KS] but respect minimum distance rules - if (mindist || dist > MELEERANGE) - continue; // behind back - } - } - } - 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; - } - } - - // [RH] Need to be sure the reactiontime is 0 if the monster is - // leaving its goal to go after a player. - if (actor->goal && actor->target == actor->goal) - actor->reactiontime = 0; - - actor->target = player->mo; - return true; - } -} - -// -// ACTION ROUTINES -// - -// -// A_Look -// Stay in state until a player is sighted. -// [RH] Will also leave state to move to goal. -// -// A_LookEx (int flags, fixed minseedist, fixed maxseedist, fixed maxheardist, fixed fov, state wakestate) -// [KS] Borrowed the A_Look code to make a parameterized version. -// - -enum LO_Flags -{ - LOF_NOSIGHTCHECK = 1, - LOF_NOSOUNDCHECK = 2, - LOF_DONTCHASEGOAL = 4, - LOF_NOSEESOUND = 8, - LOF_FULLVOLSEESOUND = 16, -}; - -DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx) -{ - ACTION_PARAM_START(6); - ACTION_PARAM_INT(flags, 0); - ACTION_PARAM_FIXED(minseedist, 1); - ACTION_PARAM_FIXED(maxseedist, 2); - ACTION_PARAM_FIXED(maxheardist, 3); - ACTION_PARAM_ANGLE(fov, 4); - ACTION_PARAM_STATE(seestate, 5); - - AActor *targ = NULL; // Shuts up gcc - fixed_t dist; - - if (self->flags5 & MF5_INCONVERSATION) - return; - - // [RH] Set goal now if appropriate - if (self->special == Thing_SetGoal && self->args[0] == 0) - { - NActorIterator iterator (NAME_PatrolPoint, self->args[1]); - self->special = 0; - self->goal = iterator.Next (); - self->reactiontime = self->args[2] * TICRATE + level.maptime; - if (self->args[3] == 0) self->flags5 &=~ MF5_CHASEGOAL; - else self->flags5 |= MF5_CHASEGOAL; - } - - self->threshold = 0; // any shot will wake up - - if (self->TIDtoHate != 0) - { - targ = self->target; - } - else - { - if (!(flags & LOF_NOSOUNDCHECK)) - { - targ = self->LastHeard; - if (targ != NULL) - { - // [RH] If the soundtarget is dead, don't chase it - if (targ->health <= 0) - { - targ = NULL; - } - else - { - dist = P_AproxDistance (targ->x - self->x, - targ->y - self->y); - - // [KS] If the target is too far away, don't respond to the sound. - if (maxheardist && dist > maxheardist) - { - targ = NULL; - self->LastHeard = NULL; - } - } - } - } - - if (targ && targ->player && (targ->player->cheats & CF_NOTARGET)) - { - return; - } - } - - // [RH] Andy Baker's stealth monsters - if (self->flags & MF_STEALTH) - { - self->visdir = -1; - } - - if (targ && (targ->flags & MF_SHOOTABLE)) - { - if (self->IsFriend (targ)) // be a little more precise! - { - if (!(self->flags4 & MF4_STANDSTILL)) - { - if (!(flags & LOF_NOSIGHTCHECK)) - { - // If we find a valid target here, the wandering logic should *not* - // be activated! If would cause the seestate to be set twice. - if (P_NewLookPlayers(self, fov, minseedist, maxseedist, !(flags & LOF_DONTCHASEGOAL))) - goto seeyou; - } - - // Let the self wander around aimlessly looking for a fight - if (!(self->flags & MF_INCHASE)) - { - if (seestate) - { - self->SetState (seestate); - } - else - { - if (self->SeeState != NULL) - { - self->SetState (self->SeeState); - } - else - { - CALL_ACTION(A_Wander, self); - } - } - } - } - } - else - { - self->target = targ; //We already have a target? - - // [KS] The target can become ourselves in rare circumstances (like - // if we committed suicide), so if that's the case, just ignore it. - if (self->target == self) self->target = NULL; - - if (self->target != NULL) - { - if (self->flags & MF_AMBUSH) - { - dist = P_AproxDistance (self->target->x - self->x, - self->target->y - self->y); - if (P_CheckSight (self, self->target, 2) && - (!minseedist || dist > minseedist) && - (!maxseedist || dist < maxseedist)) - { - goto seeyou; - } - } - else - goto seeyou; - } - } - } - - if (!(flags & LOF_NOSIGHTCHECK)) - { - if (!P_NewLookPlayers(self, fov, minseedist, maxseedist, !(flags & LOF_DONTCHASEGOAL))) - return; - } - else - { - return; - } - - // go into chase state - seeyou: - // [RH] Don't start chasing after a goal if it isn't time yet. - if (self->target == self->goal) - { - if (self->reactiontime > level.maptime) - self->target = NULL; - } - else if (self->SeeSound && !(flags & LOF_NOSEESOUND)) - { - if (flags & LOF_FULLVOLSEESOUND) - { // full volume - S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NONE); - } - else - { - S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NORM); - } - } - - if (self->target && !(self->flags & MF_INCHASE)) - { - if (seestate) - { - self->SetState (seestate); - } - else - { - self->SetState (self->SeeState); - } - } -} - -// [KS] *** End additions by me *** diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 03d489b8..b508d8f5 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -882,6 +882,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage int painchance = 0; FState * woundstate = NULL; PainChanceList * pc = NULL; + bool justhit = false; if (target == NULL || !((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_VULNERABLE))) { // Shouldn't happen @@ -893,12 +894,6 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage { if (inflictor == NULL || !(inflictor->flags4 & MF4_SPECTRAL)) { - /* - if (target->MissileState != NULL) - { - target->SetState (target->MissileState); - } - */ return; } } @@ -1285,7 +1280,7 @@ dopain: { if (pr_lightning() < 96) { - target->flags |= MF_JUSTHIT; // fight back! + justhit = true; FState * painstate = target->FindState(NAME_Pain, mod); if (painstate != NULL) target->SetState (painstate); } @@ -1300,7 +1295,7 @@ dopain: } else { - target->flags |= MF_JUSTHIT; // fight back! + justhit = true; FState * painstate = target->FindState(NAME_Pain, mod); if (painstate != NULL) target->SetState (painstate); if (mod == NAME_PoisonCloud) @@ -1345,6 +1340,11 @@ dopain: } } } + + // killough 11/98: Don't attack a friend, unless hit by that friend. + if (justhit && (target->target == source || !target->target || !target->IsFriend(target->target))) + target->flags |= MF_JUSTHIT; // fight back! + } bool AActor::OkayToSwitchTarget (AActor *other) diff --git a/src/p_local.h b/src/p_local.h index 1ac7687e..c0fbaefa 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -320,7 +320,7 @@ public: #define PT_ADDLINES 1 #define PT_ADDTHINGS 2 -AActor *P_BlockmapSearch (AActor *origin, int distance, AActor *(*func)(AActor *, int)); +AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params = NULL); AActor *P_RoughMonsterSearch (AActor *mo, int distance); // @@ -431,9 +431,10 @@ const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymo // (For ZDoom itself this doesn't make any difference here but for GZDoom it does.) // //---------------------------------------------------------------------------------- +subsector_t *P_PointInSubsector (fixed_t x, fixed_t y); inline sector_t *P_PointInSector(fixed_t x, fixed_t y) { - return R_PointInSubsector(x,y)->sector; + return P_PointInSubsector(x,y)->sector; } // diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 0c9b6569..3f8ddd32 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -40,7 +40,7 @@ #include "r_state.h" #include "templates.h" -static AActor *RoughBlockCheck (AActor *mo, int index); +static AActor *RoughBlockCheck (AActor *mo, int index, void *); //========================================================================== @@ -1279,7 +1279,7 @@ AActor *P_RoughMonsterSearch (AActor *mo, int distance) return P_BlockmapSearch (mo, distance, RoughBlockCheck); } -AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int)) +AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params) { int blockX; int blockY; @@ -1298,7 +1298,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in if (startX >= 0 && startX < bmapwidth && startY >= 0 && startY < bmapheight) { - if ( (target = check (mo, startY*bmapwidth+startX)) ) + if ( (target = check (mo, startY*bmapwidth+startX, params)) ) { // found a target right away return target; } @@ -1335,7 +1335,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in // Trace the first block section (along the top) for (; blockIndex <= firstStop; blockIndex++) { - if ( (target = check (mo, blockIndex)) ) + if ( (target = check (mo, blockIndex, params)) ) { return target; } @@ -1343,7 +1343,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in // Trace the second block section (right edge) for (blockIndex--; blockIndex <= secondStop; blockIndex += bmapwidth) { - if ( (target = check (mo, blockIndex)) ) + if ( (target = check (mo, blockIndex, params)) ) { return target; } @@ -1351,7 +1351,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in // Trace the third block section (bottom edge) for (blockIndex -= bmapwidth; blockIndex >= thirdStop; blockIndex--) { - if ( (target = check (mo, blockIndex)) ) + if ( (target = check (mo, blockIndex, params)) ) { return target; } @@ -1359,7 +1359,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in // Trace the final block section (left edge) for (blockIndex++; blockIndex > finalStop; blockIndex -= bmapwidth) { - if ( (target = check (mo, blockIndex)) ) + if ( (target = check (mo, blockIndex, params)) ) { return target; } @@ -1374,7 +1374,7 @@ AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, in // //=========================================================================== -static AActor *RoughBlockCheck (AActor *mo, int index) +static AActor *RoughBlockCheck (AActor *mo, int index, void *) { FBlockNode *link; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 9ab3a780..70c193ff 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -241,6 +241,7 @@ void AActor::Serialize (FArchive &arc) << movedir << visdir << movecount + << strafecount << target << lastenemy << LastHeard @@ -5519,11 +5520,9 @@ void PrintMiscActorInfo(AActor * query) FIXED2FLOAT(query->wallbouncefactor), query->BounceFlags); for (flagi = 0; flagi < 31; flagi++) if (query->BounceFlags & 1<alpha), query->renderflags); - /* for (flagi = 0; flagi < 31; flagi++) if (query->renderflags & 1<>3); int Pitch = Width * step_x; + /* if (hdr.img_desc&32) { ptr += (Width-1) * step_x; step_x =- step_x; } - if (!(hdr.img_desc&64)) + */ + if (!(hdr.img_desc&32)) { ptr += (Height-1) * Pitch; Pitch = -Pitch; @@ -557,12 +559,14 @@ int FTGATexture::CopyTrueColorPixels(FBitmap *bmp, int x, int y, int w, int h, i int step_x = (hdr.bpp>>3); int Pitch = Width * step_x; + /* if (hdr.img_desc&32) { ptr += (Width-1) * step_x; step_x =- step_x; } - if (!(hdr.img_desc&64)) + */ + if (!(hdr.img_desc&32)) { ptr += (Height-1) * Pitch; Pitch = -Pitch; diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index c65cb5d2..5b207c85 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -141,6 +141,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF3, NOTARGET, AActor, flags3), DEFINE_FLAG(MF3, DONTGIB, AActor, flags3), DEFINE_FLAG(MF3, NOBLOCKMONST, AActor, flags3), + DEFINE_FLAG(MF3, AVOIDMELEE, AActor, flags3), DEFINE_FLAG(MF3, FULLVOLDEATH, AActor, flags3), DEFINE_FLAG(MF3, FOILINVUL, AActor, flags3), DEFINE_FLAG(MF3, NOTELEOTHER, AActor, flags3), @@ -295,7 +296,7 @@ static FFlagDef WeaponFlags[] = DEFINE_FLAG(WIF, POWERED_UP, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, STAFF2_KICKBACK, AWeapon, WeaponFlags), DEFINE_FLAG(WIF_BOT, EXPLOSIVE, AWeapon, WeaponFlags), - DEFINE_FLAG2(WIF_BOT_MELEE, MELEEWEAPON, AWeapon, WeaponFlags), + DEFINE_FLAG(WIF, MELEEWEAPON, AWeapon, WeaponFlags), DEFINE_FLAG(WIF_BOT, BFG, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, CHEATNOTWEAPON, AWeapon, WeaponFlags), DEFINE_FLAG(WIF, NO_AUTO_SWITCH, AWeapon, WeaponFlags), diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index f04c6ba8..4f29d272 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -130,15 +130,15 @@ void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int ind break; // the bounce flags will set the compatibility bounce modes to remain compatible case DEPF_HERETICBOUNCE: - defaults->BounceFlags &= ~BOUNCE_TypeMask; + defaults->BounceFlags &= ~(BOUNCE_TypeMask|BOUNCE_UseSeeSound); if (set) defaults->BounceFlags |= BOUNCE_HereticCompat; break; case DEPF_HEXENBOUNCE: - defaults->BounceFlags &= ~BOUNCE_TypeMask; + defaults->BounceFlags &= ~(BOUNCE_TypeMask|BOUNCE_UseSeeSound); if (set) defaults->BounceFlags |= BOUNCE_HexenCompat; break; case DEPF_DOOMBOUNCE: - defaults->BounceFlags &= ~BOUNCE_TypeMask; + defaults->BounceFlags &= ~(BOUNCE_TypeMask|BOUNCE_UseSeeSound); if (set) defaults->BounceFlags |= BOUNCE_DoomCompat; break; case DEPF_PICKUPFLASH: diff --git a/src/version.h b/src/version.h index c5846e74..6ee0c795 100644 --- a/src/version.h +++ b/src/version.h @@ -77,7 +77,7 @@ // SAVESIG should match SAVEVER. // MINSAVEVER is the minimum level snapshot version that can be loaded. -#define MINSAVEVER 1823 +#define MINSAVEVER 1848 #if ZD_SVN_REVISION_NUMBER < MINSAVEVER // Never write a savegame with a version lower than what we need diff --git a/wadsrc_bm/brightmaps.vcproj b/wadsrc_bm/brightmaps.vcproj index 4c3919d1..c0f0243b 100644 --- a/wadsrc_bm/brightmaps.vcproj +++ b/wadsrc_bm/brightmaps.vcproj @@ -2,7 +2,7 @@