From 1b7c07df652b1142853706b7b296546f122a4907 Mon Sep 17 00:00:00 2001 From: ChillyDoom <ChillyDoom> Date: Sat, 25 Oct 2014 14:58:10 +0100 Subject: [PATCH 01/20] - Fixed: Bots added by different setting controllers could be assigned the same player number. --- src/b_bot.cpp | 4 +- src/b_bot.h | 14 ++++- src/b_game.cpp | 159 ++++++++++++++++++++++++++++------------------- src/d_net.cpp | 2 +- src/d_protocol.h | 2 +- src/p_saveg.cpp | 2 +- 6 files changed, 111 insertions(+), 72 deletions(-) diff --git a/src/b_bot.cpp b/src/b_bot.cpp index 969d57a1b..eb2052a26 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -125,7 +125,7 @@ void FCajunMaster::ClearPlayer (int i, bool keepTeam) bot = bot->next; if (bot) { - bot->inuse = false; + bot->inuse = BOTINUSE_No; bot->lastteam = keepTeam ? players[i].userinfo.GetTeam() : TEAM_NONE; } if (players[i].Bot != NULL) @@ -172,7 +172,7 @@ CCMD (listbots) while (thebot) { - Printf ("%s%s\n", thebot->name, thebot->inuse ? " (active)" : ""); + Printf ("%s%s\n", thebot->name, thebot->inuse == BOTINUSE_Yes ? " (active)" : ""); thebot = thebot->next; count++; } diff --git a/src/b_bot.h b/src/b_bot.h index 51fe64129..375b09abb 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -60,6 +60,13 @@ struct botskill_t FArchive &operator<< (FArchive &arc, botskill_t &skill); +enum +{ + BOTINUSE_No, + BOTINUSE_Waiting, + BOTINUSE_Yes, +}; + //Info about all bots in the bots.cfg //Updated during each level start. //Info given to bots when they're spawned. @@ -69,7 +76,7 @@ struct botinfo_t char *name; char *info; botskill_t skill; - bool inuse; + int inuse; int lastteam; }; @@ -88,7 +95,7 @@ public: bool SpawnBot (const char *name, int color = NOCOLOR); bool LoadBots (); void ForgetBots (); - void DoAddBot (BYTE **stream); + void TryAddBot (BYTE **stream, int player); void RemoveAllBots (bool fromlist); void DestroyAllBots (); @@ -122,6 +129,9 @@ public: bool m_Thinking; private: + //(B_Game.c) + bool DoAddBot (BYTE *info, botskill_t skill); + //(B_Func.c) bool Reachable (AActor *actor, AActor *target); void Dofire (AActor *actor, ticcmd_t *cmd); diff --git a/src/b_game.cpp b/src/b_game.cpp index 807ec2b46..f13c168db 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -89,8 +89,6 @@ enum BOTCFG_TEAM }; -static bool waitingforspawn[MAXPLAYERS]; - FCajunMaster::~FCajunMaster() { ForgetBots(); @@ -162,8 +160,6 @@ void FCajunMaster::Main (int buf) void FCajunMaster::Init () { - int i; - botnum = 0; firstthing = NULL; spawn_tries = 0; @@ -172,11 +168,6 @@ void FCajunMaster::Init () body1 = NULL; body2 = NULL; - for (i = 0; i < MAXPLAYERS; i++) - { - waitingforspawn[i] = false; - } - if (ctf && teamplay == false) teamplay = true; //Need teamplay for ctf. (which is not done yet) @@ -192,7 +183,7 @@ void FCajunMaster::Init () while (thebot != NULL) { - thebot->inuse = false; + thebot->inuse = BOTINUSE_No; thebot = thebot->next; } } @@ -232,12 +223,10 @@ void FCajunMaster::End () //The color parameter can be either a //color (range from 0-10), or = NOCOLOR. //The color parameter overides bots -//induvidual colors if not = NOCOLOR. +//individual colors if not = NOCOLOR. bool FCajunMaster::SpawnBot (const char *name, int color) { - int playernumber; - //COLORS static const char colors[11][17] = { @@ -254,36 +243,31 @@ bool FCajunMaster::SpawnBot (const char *name, int color) "\\color\\cf df 90" //10 = Bleached Bone }; - for (playernumber = 0; playernumber < MAXPLAYERS; playernumber++) - { - if (!playeringame[playernumber] && !waitingforspawn[playernumber]) - { - break; - } - } - - if (playernumber == MAXPLAYERS) - { - Printf ("The maximum of %d players/bots has been reached\n", MAXPLAYERS); - return false; - } - botinfo_t *thebot; + int botshift; if (name) { thebot = botinfo; // Check if exist or already in the game. + botshift = 0; while (thebot && stricmp (name, thebot->name)) + { thebot = thebot->next; + botshift++; + } if (thebot == NULL) { Printf ("couldn't find %s in %s\n", name, BOTFILENAME); return false; } - else if (thebot->inuse) + else if (thebot->inuse == BOTINUSE_Waiting) + { + return false; + } + else if (thebot->inuse == BOTINUSE_Yes) { Printf ("%s is already in the thick\n", name); return false; @@ -296,9 +280,13 @@ bool FCajunMaster::SpawnBot (const char *name, int color) { int rnum = (pr_botspawn() % loaded_bots); thebot = botinfo; + botshift = 0; while (rnum) + { --rnum, thebot = thebot->next; - if (!thebot->inuse) + botshift++; + } + if (thebot->inuse == BOTINUSE_No) vacant = true; } } @@ -308,10 +296,10 @@ bool FCajunMaster::SpawnBot (const char *name, int color) return false; } - waitingforspawn[playernumber] = true; + thebot->inuse = BOTINUSE_Waiting; Net_WriteByte (DEM_ADDBOT); - Net_WriteByte (playernumber); + Net_WriteByte (botshift); { //Set color. char concat[512]; @@ -332,61 +320,104 @@ bool FCajunMaster::SpawnBot (const char *name, int color) Net_WriteByte(thebot->skill.reaction); Net_WriteByte(thebot->skill.isp); - thebot->inuse = true; - - //Increment this. - botnum++; - return true; } -void FCajunMaster::DoAddBot (BYTE **stream) +void FCajunMaster::TryAddBot (BYTE **stream, int player) { - int bnum = ReadByte (stream); + int botshift = ReadByte (stream); char *info = ReadString (stream); - BYTE *infob = (BYTE *)info; botskill_t skill; skill.aiming = ReadByte (stream); skill.perfection = ReadByte (stream); skill.reaction = ReadByte (stream); skill.isp = ReadByte (stream); - D_ReadUserInfoStrings (bnum, &infob, false); + botinfo_t *thebot = NULL; + + if (consoleplayer == player) + { + thebot = botinfo; + + while (botshift > 0) + { + thebot = thebot->next; + botshift--; + } + } + + if (DoAddBot ((BYTE *)info, skill)) + { + if (consoleplayer == Net_Arbitrator) + { + //Increment this. + botnum++; + } + + if (thebot != NULL) + { + thebot->inuse = BOTINUSE_Yes; + } + } + else + { + if (thebot != NULL) + { + thebot->inuse = BOTINUSE_No; + } + } delete[] info; +} + +bool FCajunMaster::DoAddBot (BYTE *info, botskill_t skill) +{ + int bnum; + + for (bnum = 0; bnum < MAXPLAYERS; bnum++) + { + if (!playeringame[bnum]) + { + break; + } + } + + if (bnum == MAXPLAYERS) + { + Printf ("The maximum of %d players/bots has been reached\n", MAXPLAYERS); + return false; + } + + D_ReadUserInfoStrings (bnum, &info, false); if (!deathmatch && playerstarts[bnum].type == 0) { Printf ("%s tried to join, but there was no player %d start\n", players[bnum].userinfo.GetName(), bnum+1); ClearPlayer (bnum, false); // Make the bot inactive again - if (botnum > 0) - { - botnum--; - } + return false; } + + multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost). + players[bnum].Bot = new DBot; + GC::WriteBarrier (players[bnum].Bot); + players[bnum].Bot->skill = skill; + playeringame[bnum] = true; + players[bnum].mo = NULL; + players[bnum].playerstate = PST_ENTER; + + if (teamplay) + Printf ("%s joined the %s team\n", players[bnum].userinfo.GetName(), Teams[players[bnum].userinfo.GetTeam()].GetName()); else + Printf ("%s joined the game\n", players[bnum].userinfo.GetName()); + + G_DoReborn (bnum, true); + if (StatusBar != NULL) { - multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost). - players[bnum].Bot = new DBot; - GC::WriteBarrier (players[bnum].Bot); - players[bnum].Bot->skill = skill; - playeringame[bnum] = true; - players[bnum].mo = NULL; - players[bnum].playerstate = PST_ENTER; - - if (teamplay) - Printf ("%s joined the %s team\n", players[bnum].userinfo.GetName(), Teams[players[bnum].userinfo.GetTeam()].GetName()); - else - Printf ("%s joined the game\n", players[bnum].userinfo.GetName()); - - G_DoReborn (bnum, true); - if (StatusBar != NULL) - { - StatusBar->MultiplayerChanged (); - } + StatusBar->MultiplayerChanged (); } - waitingforspawn[bnum] = false; + + return true; } void FCajunMaster::RemoveAllBots (bool fromlist) @@ -421,8 +452,6 @@ void FCajunMaster::RemoveAllBots (bool fromlist) if (fromlist) { wanted_botnum = 0; - for (i = 0; i < MAXPLAYERS; i++) - waitingforspawn[i] = false; } botnum = 0; } diff --git a/src/d_net.cpp b/src/d_net.cpp index 89dc36d69..3d0d20b41 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2250,7 +2250,7 @@ void Net_DoCommand (int type, BYTE **stream, int player) break; case DEM_ADDBOT: - bglobal.DoAddBot (stream); + bglobal.TryAddBot (stream, player); break; case DEM_KILLBOTS: diff --git a/src/d_protocol.h b/src/d_protocol.h index 0d11c7760..f75ee1b59 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -112,7 +112,7 @@ enum EDemoCommand DEM_DROPPLAYER, // 13 Not implemented, takes a byte DEM_CHANGEMAP, // 14 Name of map to change to DEM_SUICIDE, // 15 Player wants to die - DEM_ADDBOT, // 16 Byte: player#, String: userinfo for bot, 4 Bytes: skill (aiming, perfection, reaction, isp) + DEM_ADDBOT, // 16 Byte: botshift, String: userinfo for bot, 4 Bytes: skill (aiming, perfection, reaction, isp) DEM_KILLBOTS, // 17 Remove all bots from the world DEM_INVUSEALL, // 18 Use every item (panic!) DEM_INVUSE, // 19 4 bytes: ID of item to use diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 5e9ecbdba..a677420f5 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -280,7 +280,7 @@ static void CopyPlayer (player_t *dst, player_t *src, const char *name) } if (thebot) { - thebot->inuse = true; + thebot->inuse = BOTINUSE_Yes; } bglobal.botnum++; dst->userinfo.TransferFrom(uibackup2); From 82ac6c999ef0edd7d2123205252ac152b7d34a41 Mon Sep 17 00:00:00 2001 From: Edward Richardson <Edward850@crantime.org> Date: Sun, 26 Oct 2014 04:14:52 +1300 Subject: [PATCH 02/20] Destroy old player mobjs when starting new games --- src/g_level.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/g_level.cpp b/src/g_level.cpp index 525f67318..f21a1dfe5 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -236,6 +236,18 @@ void G_NewInit () { int i; + // Destory all old player refrences that may still exist + TThinkerIterator<APlayerPawn> it(STAT_TRAVELLING); + APlayerPawn *pawn, *next; + + next = it.Next(); + while ((pawn = next) != NULL) + { + next = it.Next(); + pawn->flags |= MF_NOSECTOR | MF_NOBLOCKMAP; + pawn->Destroy(); + } + G_ClearSnapshots (); ST_SetNeedRefresh(); netgame = false; From b58595734ded02258c269bf4fc42677a74932a65 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers <coelckers@zdoom.fake> Date: Sat, 25 Oct 2014 17:37:45 +0200 Subject: [PATCH 03/20] - removed accidental line duplication. --- src/gi.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gi.cpp b/src/gi.cpp index a17e97631..b0edf2a04 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -293,7 +293,6 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_STRING(mCheatKey, "cheatKey") GAMEINFOKEY_STRING(mEasyKey, "easyKey") GAMEINFOKEY_STRING(TitlePage, "titlePage") - GAMEINFOKEY_STRING(TitlePage, "titlePage") GAMEINFOKEY_STRINGARRAY(creditPages, "addcreditPage", 8, false) GAMEINFOKEY_STRINGARRAY(creditPages, "CreditPage", 8, true) GAMEINFOKEY_STRINGARRAY(PlayerClasses, "addplayerclasses", 0, false) From be4b253215be99ae0de90b7b53bce267db9a685f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers <coelckers@zdoom.fake> Date: Sat, 25 Oct 2014 18:18:35 +0200 Subject: [PATCH 04/20] - use a separate sound for the net notches on the startup screen. --- src/win32/st_start.cpp | 2 +- wadsrc/static/sndinfo.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/win32/st_start.cpp b/src/win32/st_start.cpp index 04b52925e..af7f7ad98 100644 --- a/src/win32/st_start.cpp +++ b/src/win32/st_start.cpp @@ -767,7 +767,7 @@ void FHexenStartupScreen::NetProgress(int count) y = ST_NETPROGRESS_Y; ST_Util_DrawBlock (StartupBitmap, NetNotchBits, x, y, ST_NETNOTCH_WIDTH / 2, ST_NETNOTCH_HEIGHT); } - S_Sound (CHAN_BODY, "Drip", 1, ATTN_NONE); + S_Sound (CHAN_BODY, "misc/netnotch", 1, ATTN_NONE); I_GetEvent (); } } diff --git a/wadsrc/static/sndinfo.txt b/wadsrc/static/sndinfo.txt index 5508cd89b..be2ecd987 100644 --- a/wadsrc/static/sndinfo.txt +++ b/wadsrc/static/sndinfo.txt @@ -985,6 +985,7 @@ $alias menu/clear PlatformStop // Hexen does not have ripslop sound like Heretic misc/ripslop dsempty +misc/netnotch blddrp1 $alias intermission/cooptotal *death $alias intermission/nextstage DoorCloseLight From f802d7a44c172709daccef7364a237960c06d748 Mon Sep 17 00:00:00 2001 From: MajorCooke <paul.growney22@gmail.com> Date: Mon, 27 Oct 2014 21:35:55 -0500 Subject: [PATCH 05/20] - Added +FULLMASS. Actors will be excluded from damage/radius thrusting of all sorts by explosions or damage of any kind. They will also never deal impact damage to other enemies, nor will they damage themselves from being too close to a wall. --- src/actor.h | 1 + src/p_interaction.cpp | 3 ++- src/p_map.cpp | 40 +++++++++++++++++++--------------- src/thingdef/thingdef_data.cpp | 1 + 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/actor.h b/src/actor.h index f1c733ab2..6ae45f4b7 100644 --- a/src/actor.h +++ b/src/actor.h @@ -344,6 +344,7 @@ enum MF7_HARMFRIENDS = 0x00000020, // is allowed to harm friendly monsters. MF7_BUDDHA = 0x00000040, // Behaves just like the buddha cheat. MF7_FOILBUDDHA = 0x00000080, // Similar to FOILINVUL, foils buddha mode. + MF7_FULLMASS = 0x00000100, // Thrusting functions do not take, and do not give thrust (damage) to actors with this flag. // --- mobj.renderflags --- diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 2ac29e11c..0a615d3cc 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1097,6 +1097,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, && !(target->flags & MF_NOCLIP) && !(inflictor->flags2 & MF2_NODMGTHRUST) && !(flags & DMG_THRUSTLESS) + && !(target->flags7 & MF7_FULLMASS) && (source == NULL || source->player == NULL || !(source->flags2 & MF2_NODMGTHRUST))) { int kickback; @@ -1324,7 +1325,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, if (target->health <= 0) { if ((target->flags7 & MF7_BUDDHA) && (damage < TELEFRAG_DAMAGE) && (!(inflictor->flags3 & MF7_FOILBUDDHA) && !(flags & DMG_FOILBUDDHA))) - { //Make sure FOILINVUL flags work here too for monsters. Or perhaps consider a FOILBUDDHA flag... + { //FOILBUDDHA or Telefrag damage must kill it. target->health = 1; } else diff --git a/src/p_map.cpp b/src/p_map.cpp index 43b16a506..3c17115ff 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4679,7 +4679,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo if (!(flags & RADF_NODAMAGE)) newdam = P_DamageMobj(thing, bombspot, bombsource, damage, bombmod); - else if (thing->player == NULL && !(flags & RADF_NOIMPACTDAMAGE)) + else if (thing->player == NULL && (!(flags & RADF_NOIMPACTDAMAGE) && !(thing->flags7 & MF7_FULLMASS))) thing->flags2 |= MF2_BLASTED; if (!(thing->flags & MF_ICECORPSE)) @@ -4691,25 +4691,29 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo { if (bombsource == NULL || !(bombsource->flags2 & MF2_NODMGTHRUST)) { - thrust = points * 0.5f / (double)thing->Mass; - if (bombsource == thing) + if (!(thing->flags7 & MF7_FULLMASS)) { - thrust *= selfthrustscale; + + thrust = points * 0.5f / (double)thing->Mass; + if (bombsource == thing) + { + thrust *= selfthrustscale; + } + velz = (double)(thing->z + (thing->height >> 1) - bombspot->z) * thrust; + if (bombsource != thing) + { + velz *= 0.5f; + } + else + { + velz *= 0.8f; + } + angle_t ang = R_PointToAngle2(bombspot->x, bombspot->y, thing->x, thing->y) >> ANGLETOFINESHIFT; + thing->velx += fixed_t(finecosine[ang] * thrust); + thing->vely += fixed_t(finesine[ang] * thrust); + if (!(flags & RADF_NODAMAGE)) + thing->velz += (fixed_t)velz; // this really doesn't work well } - velz = (double)(thing->z + (thing->height >> 1) - bombspot->z) * thrust; - if (bombsource != thing) - { - velz *= 0.5f; - } - else - { - velz *= 0.8f; - } - angle_t ang = R_PointToAngle2(bombspot->x, bombspot->y, thing->x, thing->y) >> ANGLETOFINESHIFT; - thing->velx += fixed_t(finecosine[ang] * thrust); - thing->vely += fixed_t(finesine[ang] * thrust); - if (!(flags & RADF_NODAMAGE)) - thing->velz += (fixed_t)velz; // this really doesn't work well } } } diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index 90c3313a6..fe1cec588 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -244,6 +244,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF7, HARMFRIENDS, AActor, flags7), DEFINE_FLAG(MF7, BUDDHA, AActor, flags7), DEFINE_FLAG(MF7, FOILBUDDHA, AActor, flags7), + DEFINE_FLAG(MF7, FULLMASS, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From c01d1a8003dcfb90abd3170545ec3891e5f67f79 Mon Sep 17 00:00:00 2001 From: MajorCooke <paul.growney22@gmail.com> Date: Mon, 27 Oct 2014 22:29:10 -0500 Subject: [PATCH 06/20] - Added DMSS_NOPROTECT. Bypasses PowerProtection inventory items. --- src/p_interaction.cpp | 10 +++++----- src/p_local.h | 1 + src/thingdef/thingdef_codeptr.cpp | 3 +++ wadsrc/static/actors/constants.txt | 1 + 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 0a615d3cc..db6dcdc7d 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1053,8 +1053,8 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, return -1; } } - // Handle passive damage modifiers (e.g. PowerProtection) - if (target->Inventory != NULL) + // Handle passive damage modifiers (e.g. PowerProtection), provided they are not afflicted with protection penetrating powers. + if ((target->Inventory != NULL) && !(flags & DMG_NO_PROTECT)) { int olddam = damage; target->Inventory->ModifyDamage(olddam, mod, damage, true); @@ -1592,7 +1592,7 @@ bool AActor::OkayToSwitchTarget (AActor *other) bool P_PoisonPlayer (player_t *player, AActor *poisoner, AActor *source, int poison) { - if((player->cheats&CF_GODMODE) || (player->mo->flags2 & MF2_INVULNERABLE)) + if((player->cheats&CF_GODMODE) || (player->mo->flags2 & MF2_INVULNERABLE) || (player->cheats & CF_GODMODE2)) { return false; } @@ -1643,8 +1643,8 @@ void P_PoisonDamage (player_t *player, AActor *source, int damage, { return; } - if (damage < TELEFRAG_DAMAGE && ((target->flags2 & MF2_INVULNERABLE) || - (player->cheats & CF_GODMODE))) + if ((damage < TELEFRAG_DAMAGE && ((target->flags2 & MF2_INVULNERABLE) || + (player->cheats & CF_GODMODE))) || (player->cheats & CF_GODMODE2)) { // target is invulnerable return; } diff --git a/src/p_local.h b/src/p_local.h index f7e473845..dec80ecaa 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -560,6 +560,7 @@ enum EDmgFlags DMG_PLAYERATTACK = 32, DMG_FOILINVUL = 64, DMG_FOILBUDDHA = 128, + DMG_NO_PROTECT = 256, }; diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 6a1cf6e67..a8f0a4d40 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -4832,6 +4832,7 @@ enum DMSS DMSS_KILL = 4, DMSS_NOFACTOR = 8, DMSS_FOILBUDDHA = 16, + DMSS_NOPROTECT = 32, }; static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags) @@ -4847,6 +4848,8 @@ static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageTy dmgFlags += DMG_NO_ARMOR; if (flags & DMSS_KILL) //Kill adds the value of the damage done to it. Allows for more controlled extreme death types. amount += dmgtarget->health; + if (flags & DMSS_NOPROTECT) //Ignore PowerProtection. + dmgFlags += DMG_NO_PROTECT; if (amount > 0) P_DamageMobj(dmgtarget, self, self, amount, DamageType, dmgFlags); //Should wind up passing them through just fine. diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index f806f8224..278d4b90f 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -383,6 +383,7 @@ const int DMSS_AFFECTARMOR = 2; const int DMSS_KILL = 4; const int DMSS_NOFACTOR = 8; const int DMSS_FOILBUDDHA = 16; +const int DMSS_NOPROTECT = 32; // Flags for A_AlertMonsters const int AMF_TARGETEMITTER = 1; From 774db445ec815be0099e7b3fba08c4ffb1bc3eb0 Mon Sep 17 00:00:00 2001 From: MajorCooke <paul.growney22@gmail.com> Date: Mon, 27 Oct 2014 22:40:25 -0500 Subject: [PATCH 07/20] -Fixed: WhirlWind was still able to affect actors with the FULLMASS flag. --- src/g_heretic/a_ironlich.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp index d8c1fd285..d2e49a0f3 100644 --- a/src/g_heretic/a_ironlich.cpp +++ b/src/g_heretic/a_ironlich.cpp @@ -28,10 +28,14 @@ int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype) { int randVal; - target->angle += pr_foo.Random2() << 20; - target->velx += pr_foo.Random2() << 10; - target->vely += pr_foo.Random2() << 10; - if ((level.time & 16) && !(target->flags2 & MF2_BOSS)) + if (!(target->flags7 & MF7_FULLMASS)) + { + target->angle += pr_foo.Random2() << 20; + target->velx += pr_foo.Random2() << 10; + target->vely += pr_foo.Random2() << 10; + } + + if ((level.time & 16) && !(target->flags2 & MF2_BOSS) && !(target->flags7 & MF7_FULLMASS)) { randVal = pr_foo(); if (randVal > 160) From 6073adbeef6cb497084bad8371134648a18fe1a3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers <coelckers@zdoom.fake> Date: Tue, 28 Oct 2014 08:40:34 +0100 Subject: [PATCH 08/20] - renamed FULLMASS to DONTTHRUST. --- src/actor.h | 2 +- src/g_heretic/a_ironlich.cpp | 4 ++-- src/p_interaction.cpp | 2 +- src/p_map.cpp | 4 ++-- src/thingdef/thingdef_data.cpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/actor.h b/src/actor.h index 6ae45f4b7..6c9d53a4f 100644 --- a/src/actor.h +++ b/src/actor.h @@ -344,7 +344,7 @@ enum MF7_HARMFRIENDS = 0x00000020, // is allowed to harm friendly monsters. MF7_BUDDHA = 0x00000040, // Behaves just like the buddha cheat. MF7_FOILBUDDHA = 0x00000080, // Similar to FOILINVUL, foils buddha mode. - MF7_FULLMASS = 0x00000100, // Thrusting functions do not take, and do not give thrust (damage) to actors with this flag. + MF7_DONTTHRUST = 0x00000100, // Thrusting functions do not take, and do not give thrust (damage) to actors with this flag. // --- mobj.renderflags --- diff --git a/src/g_heretic/a_ironlich.cpp b/src/g_heretic/a_ironlich.cpp index d2e49a0f3..dba16b622 100644 --- a/src/g_heretic/a_ironlich.cpp +++ b/src/g_heretic/a_ironlich.cpp @@ -28,14 +28,14 @@ int AWhirlwind::DoSpecialDamage (AActor *target, int damage, FName damagetype) { int randVal; - if (!(target->flags7 & MF7_FULLMASS)) + if (!(target->flags7 & MF7_DONTTHRUST)) { target->angle += pr_foo.Random2() << 20; target->velx += pr_foo.Random2() << 10; target->vely += pr_foo.Random2() << 10; } - if ((level.time & 16) && !(target->flags2 & MF2_BOSS) && !(target->flags7 & MF7_FULLMASS)) + if ((level.time & 16) && !(target->flags2 & MF2_BOSS) && !(target->flags7 & MF7_DONTTHRUST)) { randVal = pr_foo(); if (randVal > 160) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index db6dcdc7d..860e30d0f 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1097,7 +1097,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, && !(target->flags & MF_NOCLIP) && !(inflictor->flags2 & MF2_NODMGTHRUST) && !(flags & DMG_THRUSTLESS) - && !(target->flags7 & MF7_FULLMASS) + && !(target->flags7 & MF7_DONTTHRUST) && (source == NULL || source->player == NULL || !(source->flags2 & MF2_NODMGTHRUST))) { int kickback; diff --git a/src/p_map.cpp b/src/p_map.cpp index 3c17115ff..b688ef43d 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -4679,7 +4679,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo if (!(flags & RADF_NODAMAGE)) newdam = P_DamageMobj(thing, bombspot, bombsource, damage, bombmod); - else if (thing->player == NULL && (!(flags & RADF_NOIMPACTDAMAGE) && !(thing->flags7 & MF7_FULLMASS))) + else if (thing->player == NULL && (!(flags & RADF_NOIMPACTDAMAGE) && !(thing->flags7 & MF7_DONTTHRUST))) thing->flags2 |= MF2_BLASTED; if (!(thing->flags & MF_ICECORPSE)) @@ -4691,7 +4691,7 @@ void P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bo { if (bombsource == NULL || !(bombsource->flags2 & MF2_NODMGTHRUST)) { - if (!(thing->flags7 & MF7_FULLMASS)) + if (!(thing->flags7 & MF7_DONTTHRUST)) { thrust = points * 0.5f / (double)thing->Mass; diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index fe1cec588..dbd1f1031 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -244,7 +244,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF7, HARMFRIENDS, AActor, flags7), DEFINE_FLAG(MF7, BUDDHA, AActor, flags7), DEFINE_FLAG(MF7, FOILBUDDHA, AActor, flags7), - DEFINE_FLAG(MF7, FULLMASS, AActor, flags7), + DEFINE_FLAG(MF7, DONTTHRUST, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From 65cb662678c29c0d66e817a0d77a18e516994cf8 Mon Sep 17 00:00:00 2001 From: Gaerzi <gaerzi@gmail.com> Date: Tue, 28 Oct 2014 21:19:01 +0100 Subject: [PATCH 09/20] Missing break in case NAME_FillColor This caused weirdness with invulnerable monsters when their fillcolor was changed. --- src/p_udmf.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 6af777b36..926e65dcc 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -690,6 +690,7 @@ public: case NAME_FillColor: th->fillcolor = CheckInt(key); + break; case NAME_Health: th->health = CheckInt(key); From 978667143c4acc49e323cb68cad0483a0b665ad8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers <coelckers@zdoom.fake> Date: Wed, 29 Oct 2014 08:54:14 +0100 Subject: [PATCH 10/20] - fixed: P_RemoveThing must not remove owned inventory items. --- src/p_things.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_things.cpp b/src/p_things.cpp index 2a93ee31e..a8d0404b6 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -402,10 +402,14 @@ void P_RemoveThing(AActor * actor) // Don't remove live players. if (actor->player == NULL || actor != actor->player->mo) { + // Don't also remove owned inventory items + if (actor->IsKindOf(RUNTIME_CLASS(AInventory)) && static_cast<AInventory*>(actor)->Owner == NULL) return; + // be friendly to the level statistics. ;) actor->ClearCounters(); actor->Destroy (); } + } bool P_Thing_Raise(AActor *thing) From c1a0ee9623637984ad01c75521b80bc410d895d2 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers <coelckers@zdoom.fake> Date: Wed, 29 Oct 2014 10:40:08 +0100 Subject: [PATCH 11/20] - fixed last commit. --- src/p_things.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_things.cpp b/src/p_things.cpp index a8d0404b6..0189848e4 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -403,7 +403,7 @@ void P_RemoveThing(AActor * actor) if (actor->player == NULL || actor != actor->player->mo) { // Don't also remove owned inventory items - if (actor->IsKindOf(RUNTIME_CLASS(AInventory)) && static_cast<AInventory*>(actor)->Owner == NULL) return; + if (actor->IsKindOf(RUNTIME_CLASS(AInventory)) && static_cast<AInventory*>(actor)->Owner != NULL) return; // be friendly to the level statistics. ;) actor->ClearCounters(); From 5977cb04d9d24265b823168ccbb663e9ff9c65a2 Mon Sep 17 00:00:00 2001 From: MajorCooke <paul.growney22@gmail.com> Date: Wed, 29 Oct 2014 12:33:25 -0500 Subject: [PATCH 12/20] - Fixed: A_Die didn't consider missiles for the function. --- src/p_enemy.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index e51d601f3..ef6136fdc 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -3161,7 +3161,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Die) ACTION_PARAM_START(1); ACTION_PARAM_NAME(damagetype, 0); - P_DamageMobj (self, NULL, NULL, self->health, damagetype, DMG_FORCED); + if (self->flags & MF_MISSILE) + P_ExplodeMissile(self, NULL, NULL); + else + P_DamageMobj (self, NULL, NULL, self->health, damagetype, DMG_FORCED); } // From 165d2887fd8bdab5e4f388c5db54e99c83e27488 Mon Sep 17 00:00:00 2001 From: MajorCooke <paul.growney22@gmail.com> Date: Wed, 29 Oct 2014 14:01:31 -0500 Subject: [PATCH 13/20] - Added: A_GiveToChildren - Added: A_TakeFromChildren - Added: A_GiveToSiblings - Added: A_TakeFromSiblings - Added the following flags for A_RadiusGive: - RGF_NOSIGHT: Exclude sight check from distance. - RGF_MISSILES: Missiles can take inventory items. --- src/thingdef/thingdef_codeptr.cpp | 85 +++++++++++++++++++++++++----- wadsrc/static/actors/actor.txt | 4 ++ wadsrc/static/actors/constants.txt | 20 +++---- 3 files changed, 87 insertions(+), 22 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index a8f0a4d40..6fafbddcf 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -1677,6 +1677,31 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToTarget) DoGiveInventory(self->target, PUSH_PARAMINFO); } +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToChildren) +{ + TThinkerIterator<AActor> it; + AActor * mo; + + while ((mo = it.Next())) + { + if (mo->master == self) DoGiveInventory(mo, PUSH_PARAMINFO); + } +} + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_GiveToSiblings) +{ + TThinkerIterator<AActor> it; + AActor * mo; + + if (self->master != NULL) + { + while ((mo = it.Next())) + { + if (mo->master == self->master && mo != self) DoGiveInventory(mo, PUSH_PARAMINFO); + } + } +} + //=========================================================================== // // A_TakeInventory @@ -1737,6 +1762,31 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromTarget) DoTakeInventory(self->target, PUSH_PARAMINFO); } +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromChildren) +{ + TThinkerIterator<AActor> it; + AActor * mo; + + while ((mo = it.Next())) + { + if (mo->master == self) DoTakeInventory(mo, PUSH_PARAMINFO); + } +} + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_TakeFromSiblings) +{ + TThinkerIterator<AActor> it; + AActor * mo; + + if (self->master != NULL) + { + while ((mo = it.Next())) + { + if (mo->master == self->master && mo != self) DoTakeInventory(mo, PUSH_PARAMINFO); + } + } +} + //=========================================================================== // // Common code for A_SpawnItem and A_SpawnItemEx @@ -4608,17 +4658,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, ACS_NamedTerminate) //========================================================================== enum RadiusGiveFlags { - RGF_GIVESELF = 1, - RGF_PLAYERS = 2, - RGF_MONSTERS = 4, - RGF_OBJECTS = 8, - RGF_VOODOO = 16, - RGF_CORPSES = 32, - RGF_MASK = 63, - RGF_NOTARGET = 64, - RGF_NOTRACER = 128, - RGF_NOMASTER = 256, - RGF_CUBE = 512, + RGF_GIVESELF = 1 << 0, + RGF_PLAYERS = 1 << 1, + RGF_MONSTERS = 1 << 2, + RGF_OBJECTS = 1 << 3, + RGF_VOODOO = 1 << 4, + RGF_CORPSES = 1 << 5, + RGF_MASK = 63, + RGF_NOTARGET = 1 << 6, + RGF_NOTRACER = 1 << 7, + RGF_NOMASTER = 1 << 8, + RGF_CUBE = 1 << 9, + RGF_NOSIGHT = 1 << 10, + RGF_MISSILES = 1 << 11, }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) @@ -4699,6 +4751,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) continue; } } + else if (thing->flags & MF_MISSILE) + { + if (!(flags & RGF_MISSILES)) + { + continue; + } + } else { continue; @@ -4724,8 +4783,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) } fixed_t dz = abs ((thing->z + thing->height/2) - (self->z + self->height/2)); - if (P_CheckSight (thing, self, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY)) - { // OK to give; target is in direct path + if (P_CheckSight (thing, self, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) || (RGF_NOSIGHT)) + { // OK to give; target is in direct path, or the monster doesn't care about it being in line of sight. AInventory *gift = static_cast<AInventory *>(Spawn (item, 0, 0, 0, NO_REPLACE)); if (gift->IsKindOf(RUNTIME_CLASS(AHealth))) { diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index 280321ad0..e253f53ac 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -312,6 +312,10 @@ ACTOR Actor native //: Thinker action native A_RemoveTarget(int flags = 0); action native A_RemoveTracer(int flags = 0); action native A_Remove(int removee, int flags = 0); + action native A_GiveToChildren(class<Inventory> itemtype, int amount = 0); + action native A_GiveToSiblings(class<Inventory> itemtype, int amount = 0); + action native A_TakeFromChildren(class<Inventory> itemtype, int amount = 0); + action native A_TakeFromSiblings(class<Inventory> itemtype, int amount = 0); action native A_CheckSightOrRange(float distance, state label); action native A_CheckRange(float distance, state label); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 278d4b90f..a43d90f96 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -191,15 +191,17 @@ const int WAF_USEPUFF = 2; enum { RGF_GIVESELF = 1, - RGF_PLAYERS = 2, - RGF_MONSTERS = 4, - RGF_OBJECTS = 8, - RGF_VOODOO = 16, - RGF_CORPSES = 32, - RGF_NOTARGET = 64, - RGF_NOTRACER = 128, - RGF_NOMASTER = 256, - RGF_CUBE = 512, + RGF_PLAYERS = 1 << 1, + RGF_MONSTERS = 1 << 2, + RGF_OBJECTS = 1 << 3, + RGF_VOODOO = 1 << 4, + RGF_CORPSES = 1 << 5, + RGF_NOTARGET = 1 << 6, + RGF_NOTRACER = 1 << 7, + RGF_NOMASTER = 1 << 8, + RGF_CUBE = 1 << 9, + RGF_NOSIGHT = 1 << 10, + RGF_MISSILES = 1 << 11, }; // Activation flags From 31611c17d572e2aab109099d047e157fd51682cc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers <coelckers@zdoom.fake> Date: Wed, 29 Oct 2014 22:00:15 +0100 Subject: [PATCH 14/20] - fixed RGF_NOSIGHT checking for A_RadiusGive. --- src/thingdef/thingdef_codeptr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 6fafbddcf..80583b587 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -4783,7 +4783,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive) } fixed_t dz = abs ((thing->z + thing->height/2) - (self->z + self->height/2)); - if (P_CheckSight (thing, self, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY) || (RGF_NOSIGHT)) + if ((flags & RGF_NOSIGHT) || P_CheckSight (thing, self, SF_IGNOREVISIBILITY|SF_IGNOREWATERBOUNDARY)) { // OK to give; target is in direct path, or the monster doesn't care about it being in line of sight. AInventory *gift = static_cast<AInventory *>(Spawn (item, 0, 0, 0, NO_REPLACE)); if (gift->IsKindOf(RUNTIME_CLASS(AHealth))) From 2f11a59be0d743b04d7a7885624ad7925a8f545c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers <coelckers@zdoom.fake> Date: Fri, 31 Oct 2014 08:57:43 +0100 Subject: [PATCH 15/20] - fixed: UDMF ceiling plane properties set the map's floor plane values. --- src/p_udmf.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index b4700e856..541d7d396 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1541,11 +1541,11 @@ public: double ulen = TVector3<double>(cp[0], cp[1], cp[2]).Length(); // normalize the vector, it must have a length of 1 - sec->floorplane.a = FLOAT2FIXED(cp[0] / ulen); - sec->floorplane.b = FLOAT2FIXED(cp[1] / ulen); - sec->floorplane.c = FLOAT2FIXED(cp[2] / ulen); - sec->floorplane.d = FLOAT2FIXED(cp[3] / ulen); - sec->floorplane.ic = FLOAT2FIXED(ulen / cp[2]); + sec->ceilingplane.a = FLOAT2FIXED(cp[0] / ulen); + sec->ceilingplane.b = FLOAT2FIXED(cp[1] / ulen); + sec->ceilingplane.c = FLOAT2FIXED(cp[2] / ulen); + sec->ceilingplane.d = FLOAT2FIXED(cp[3] / ulen); + sec->ceilingplane.ic = FLOAT2FIXED(ulen / cp[2]); } if (lightcolor == -1 && fadecolor == -1 && desaturation == -1) From c85105f5520f873f8c32bfddbf612260025b2ae4 Mon Sep 17 00:00:00 2001 From: Edward Richardson <Edward850@crantime.org> Date: Fri, 31 Oct 2014 22:50:23 +1300 Subject: [PATCH 16/20] Added cl_showsecretmessage Controls if secret notifications are displayed (def. true) --- src/p_spec.cpp | 3 ++- wadsrc/static/menudef.txt | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_spec.cpp b/src/p_spec.cpp index d58062a7e..676191555 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -714,6 +714,7 @@ void P_SectorDamage(int tag, int amount, FName type, const PClass *protectClass, //============================================================================ CVAR(Bool, showsecretsector, false, 0) +CVAR(Bool, cl_showsecretmessage, true, CVAR_ARCHIVE) void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornum) { @@ -723,7 +724,7 @@ void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornu { actor->player->secretcount++; } - if (actor->CheckLocalView (consoleplayer)) + if (cl_showsecretmessage && actor->CheckLocalView(consoleplayer)) { if (printmessage) { diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 3d5a3ea3c..408e534a8 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1098,6 +1098,7 @@ OptionMenu MessageOptions Title "MESSAGES" Option "Show messages", "show_messages", "OnOff" Option "Show obituaries", "show_obituaries", "OnOff" + Option "Show secret notifications", "cl_showsecretmessage", "OnOff" Option "Scale text in high res", "con_scaletext", "ScaleValues" Option "Minimum message level", "msg", "MessageLevels" Option "Center messages", "con_centernotify", "OnOff" From 0ff65bb43089fcae61c272b65a43987a82e11820 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers <coelckers@zdoom.fake> Date: Fri, 31 Oct 2014 21:08:13 +0100 Subject: [PATCH 17/20] - fixed: AActor::Massacre must return true only when it actually kills a monster. --- src/p_mobj.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 465a4d745..a92eed8f8 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1167,7 +1167,7 @@ bool AActor::Massacre () P_DamageMobj (this, NULL, NULL, TELEFRAG_DAMAGE, NAME_Massacre); } while (health != prevhealth && health > 0); //abort if the actor wasn't hurt. - return true; + return health <= 0; } return false; } From 938b54ccb5f62f864edcc1edf26fcd42304ddb84 Mon Sep 17 00:00:00 2001 From: MajorCooke <paul.growney22@gmail.com> Date: Fri, 31 Oct 2014 15:41:23 -0500 Subject: [PATCH 18/20] - Added TF_FORCED for A_Teleport. Forces the actor to move to the spot. --- src/thingdef/thingdef_codeptr.cpp | 18 ++++++++++++++++-- wadsrc/static/actors/constants.txt | 4 +++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 80583b587..2732337c7 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -4054,6 +4054,7 @@ enum T_Flags { TF_TELEFRAG = 1, // Allow telefrag in order to teleport. TF_RANDOMDECIDE = 2, // Randomly fail based on health. (A_Srcr2Decide) + TF_FORCED = 4, // Forget what's in the way. TF_Telefrag takes precedence though. }; DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) @@ -4103,7 +4104,20 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Teleport) fixed_t prevX = self->x; fixed_t prevY = self->y; fixed_t prevZ = self->z; - if (P_TeleportMove (self, spot->x, spot->y, spot->z, Flags & TF_TELEFRAG)) + bool teleResult = false; + + //Take precedence and cooperate with telefragging first. + if (P_TeleportMove(self, spot->x, spot->y, spot->z, Flags & TF_TELEFRAG)) + teleResult = true; + + if ((!(teleResult)) && (Flags & TF_FORCED)) + { + //If for some reason the original move didn't work, regardless of telefrag, force it to move. + self->SetOrigin(spot->x, spot->y, spot->z); + teleResult = true; + } + + if (teleResult) { ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains! @@ -4509,7 +4523,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp) self->PrevY = self->y + reference->PrevY - reference->y; self->PrevZ = self->z + reference->PrevZ - reference->z; } - else if (! (flags & WARPF_INTERPOLATE)) + else if (!(flags & WARPF_INTERPOLATE)) { self->PrevX = self->x; self->PrevY = self->y; diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index a43d90f96..78741e059 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -181,7 +181,9 @@ const int FPF_AIMATANGLE = 1; const int FPF_TRANSFERTRANSLATION = 2; // Flags for A_Teleport -const int TF_TELEFRAG = 1;const int TF_RANDOMDECIDE = 2; +const int TF_TELEFRAG = 1; +const int TF_RANDOMDECIDE = 2; +const int TF_FORCED = 4; // Flags for A_WolfAttack const int WAF_NORANDOM = 1; From eceb37aa64d2286ab181768aefbab470de17f257 Mon Sep 17 00:00:00 2001 From: Edward Richardson <Edward850@crantime.org> Date: Sat, 1 Nov 2014 17:47:29 +1300 Subject: [PATCH 19/20] Added recordmap for recording demos from console recordmap <filename> <map name> Starts a new game from the specified map recording to the specified filename --- src/d_event.h | 1 + src/d_main.cpp | 1 + src/doomstat.h | 2 ++ src/g_game.cpp | 16 ++++++++++++++++ src/g_level.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 60 insertions(+) diff --git a/src/d_event.h b/src/d_event.h index 5bd4b02e0..7a9b48eb8 100644 --- a/src/d_event.h +++ b/src/d_event.h @@ -61,6 +61,7 @@ typedef enum ga_loadlevel, ga_newgame, ga_newgame2, + ga_recordgame, ga_loadgame, ga_loadgamehidecon, ga_loadgameplaydemo, diff --git a/src/d_main.cpp b/src/d_main.cpp index 79c899085..e08b1539e 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1338,6 +1338,7 @@ CCMD (endgame) { gameaction = ga_fullconsole; demosequence = -1; + G_CheckDemoStatus(); } } diff --git a/src/doomstat.h b/src/doomstat.h index 92ab5b8f8..1559609f1 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -136,6 +136,8 @@ extern int consoleplayer; // Disable save/end game? extern bool usergame; +extern FString newdemoname; +extern FString newdemomap; extern bool demoplayback; extern bool demorecording; extern int demover; diff --git a/src/g_game.cpp b/src/g_game.cpp index 8419fc017..1ea1c6b68 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -162,6 +162,8 @@ int consoleplayer; // player taking events int gametic; CVAR(Bool, demo_compress, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); +FString newdemoname; +FString newdemomap; FString demoname; bool demorecording; bool demoplayback; @@ -1048,6 +1050,10 @@ void G_Ticker () case ga_loadlevel: G_DoLoadLevel (-1, false); break; + case ga_recordgame: + G_CheckDemoStatus(); + G_RecordDemo(newdemoname); + G_BeginRecording(newdemomap); case ga_newgame2: // Silence GCC (see above) case ga_newgame: G_DoNewGame (); @@ -2434,6 +2440,16 @@ void G_DeferedPlayDemo (const char *name) CCMD (playdemo) { + if (netgame) + { + Printf("End your current netgame first!"); + return; + } + if (demorecording) + { + Printf("End your current demo first!"); + return; + } if (argv.argc() > 1) { G_DeferedPlayDemo (argv[1]); diff --git a/src/g_level.cpp b/src/g_level.cpp index f21a1dfe5..2a2d6471a 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -199,6 +199,46 @@ CCMD (map) // //========================================================================== +CCMD(recordmap) +{ + if (netgame) + { + Printf("You cannot record a new game while in a netgame."); + return; + } + if (argv.argc() > 2) + { + try + { + if (!P_CheckMapData(argv[2])) + { + Printf("No map %s\n", argv[2]); + } + else + { + G_DeferedInitNew(argv[2]); + gameaction = ga_recordgame; + newdemoname = argv[1]; + newdemomap = argv[2]; + } + } + catch (CRecoverableError &error) + { + if (error.GetMessage()) + Printf("%s", error.GetMessage()); + } + } + else + { + Printf("Usage: recordmap <filename> <map name>\n"); + } +} + +//========================================================================== +// +// +//========================================================================== + CCMD (open) { if (netgame) From 2e085b23188b3472f1595340fe04eb85bf19f459 Mon Sep 17 00:00:00 2001 From: MajorCooke <paul.growney22@gmail.com> Date: Sat, 1 Nov 2014 00:00:29 -0500 Subject: [PATCH 20/20] - Added ALLOWPAIN flag. Monsters with this flag can enter pain states, regardless of invulnerability or damage absorption. - Fixed: god2 cheat wasn't being considered for drowning and thrusting. --- src/actor.h | 1 + src/p_interaction.cpp | 88 +++++++++++++++++++++++++++------- src/p_mobj.cpp | 2 +- src/p_user.cpp | 3 +- src/thingdef/thingdef_data.cpp | 1 + 5 files changed, 77 insertions(+), 18 deletions(-) diff --git a/src/actor.h b/src/actor.h index 6c9d53a4f..22f4cb776 100644 --- a/src/actor.h +++ b/src/actor.h @@ -345,6 +345,7 @@ enum MF7_BUDDHA = 0x00000040, // Behaves just like the buddha cheat. MF7_FOILBUDDHA = 0x00000080, // Similar to FOILINVUL, foils buddha mode. MF7_DONTTHRUST = 0x00000100, // Thrusting functions do not take, and do not give thrust (damage) to actors with this flag. + MF7_ALLOWPAIN = 0x00000200, // Invulnerable or immune (via damagefactors) actors can still react to taking damage even if they don't. // --- mobj.renderflags --- diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 860e30d0f..f318ed3b3 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -938,6 +938,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FState * woundstate = NULL; PainChanceList * pc = NULL; bool justhit = false; + bool plrDontThrust = false; + bool invulpain = false; + int fakeDamage = 0; + int holdDamage = 0; if (target == NULL || !((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_VULNERABLE))) { // Shouldn't happen @@ -972,7 +976,14 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, { if (inflictor == NULL || (!(inflictor->flags3 & MF3_FOILINVUL) && !(flags & DMG_FOILINVUL))) { - return -1; + if (target->flags7 & MF7_ALLOWPAIN) + { + invulpain = true; //This returns -1 later. + fakeDamage = damage; + goto fakepain; //The label is above the massive pile of checks. + } + else + return -1; } } else @@ -980,11 +991,21 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // Players are optionally excluded from getting thrust by damage. if (static_cast<APlayerPawn *>(target)->PlayerFlags & PPF_NOTHRUSTWHENINVUL) { - return -1; + if (target->flags7 & MF7_ALLOWPAIN) + plrDontThrust = 1; + else + return -1; } } } + if ((target->flags7 & MF7_ALLOWPAIN) && (damage < TELEFRAG_DAMAGE)) + { + //Intentionally do not jump to fakepain because the damage hasn't been dished out yet. + //Once it's dished out, THEN we can disregard damage factors affecting pain chances. + fakeDamage = damage; + } + if (inflictor != NULL) { if (inflictor->flags5 & MF5_PIERCEARMOR) @@ -1010,6 +1031,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // Invulnerable, and won't wake up return -1; } + player = target->player; if (player && damage > 1 && damage < TELEFRAG_DAMAGE) { @@ -1032,10 +1054,13 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, return -1; } } + if (damage > 0) + damage = inflictor->DoSpecialDamage (target, damage, mod); - damage = inflictor->DoSpecialDamage (target, damage, mod); if (damage == -1) { + if (target->flags7 & MF7_ALLOWPAIN) //Hold off ending the function before we can deal the pain chances. + goto fakepain; return -1; } } @@ -1058,12 +1083,15 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, { int olddam = damage; target->Inventory->ModifyDamage(olddam, mod, damage, true); - if (olddam != damage && damage <= 0) - { // Still allow FORCEPAIN + if (((target->flags7 & MF7_ALLOWPAIN) && (fakeDamage <= 0)) || (olddam != damage && damage <= 0)) + { // Still allow FORCEPAIN and make sure we're still passing along fake damage to hit enemies for their pain states. if (MustForcePain(target, inflictor)) { goto dopain; } + else if (target->flags7 & MF7_ALLOWPAIN) + goto fakepain; + return -1; } } @@ -1081,19 +1109,25 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, { goto dopain; } + else if (target->flags7 & MF7_ALLOWPAIN) + goto fakepain; + return -1; } } - - damage = target->TakeSpecialDamage (inflictor, source, damage, mod); + if (damage > 0) + damage = target->TakeSpecialDamage (inflictor, source, damage, mod); } if (damage == -1) { + if (target->flags7 & MF7_ALLOWPAIN) + goto fakepain; + return -1; } // Push the target unless the source's weapon's kickback is 0. // (i.e. Gauntlets/Chainsaw) - if (inflictor && inflictor != target // [RH] Not if hurting own self + if (!(plrDontThrust) && inflictor && inflictor != target // [RH] Not if hurting own self && !(target->flags & MF_NOCLIP) && !(inflictor->flags2 & MF2_NODMGTHRUST) && !(flags & DMG_THRUSTLESS) @@ -1134,11 +1168,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, { fltthrust = clamp((damage * 0.125 * kickback) / target->Mass, 0., fltthrust); } - thrust = FLOAT2FIXED(fltthrust); - - // Don't apply ultra-small damage thrust - if (thrust < FRACUNIT/100) thrust = 0; + // Don't apply ultra-small damage thrust. + if (thrust < FRACUNIT / 100) + thrust = 0; // make fall forwards sometimes if ((damage < 40) && (damage > target->health) @@ -1147,8 +1180,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, // [RH] But only if not too fast and not flying && thrust < 10*FRACUNIT && !(target->flags & MF_NOGRAVITY) - && (inflictor == NULL || !(inflictor->flags5 & MF5_NOFORWARDFALL)) - ) + && (inflictor == NULL || !(inflictor->flags5 & MF5_NOFORWARDFALL))) { ang += ANG180; thrust *= 4; @@ -1215,6 +1247,12 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, (player->cheats & CF_GODMODE2) || (player->mo->flags5 & MF5_NODAMAGE)) //Absolutely no hurting if NODAMAGE is involved. Same for GODMODE2. { // player is invulnerable, so don't hurt him + if (player->mo->flags7 & MF7_ALLOWPAIN) + { + invulpain = true; + fakeDamage = damage; + goto fakepain; + } return -1; } @@ -1232,7 +1270,8 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, { // If MF6_FORCEPAIN is set, make the player enter the pain state. if (!(target->flags5 & MF5_NOPAIN) && inflictor != NULL && - (inflictor->flags6 & MF6_FORCEPAIN) && !(inflictor->flags5 & MF5_PAINLESS)) + (inflictor->flags6 & MF6_FORCEPAIN) && !(inflictor->flags5 & MF5_PAINLESS) && + (!(player->mo->flags2 & MF2_INVULNERABLE))) { goto dopain; } @@ -1296,7 +1335,10 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, damage = newdam; if (damage <= 0) { - return damage; + if (target->flags7 & MF7_ALLOWPAIN) + goto fakepain; + else + return damage; } } @@ -1383,6 +1425,12 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, } } +fakepain: //Needed so we can skip the rest of the above, but still obey the original rules. + if (target->flags7 & MF7_ALLOWPAIN && (fakeDamage != damage)) + { + holdDamage = damage; + damage = fakeDamage; + } if (!(target->flags5 & MF5_NOPAIN) && (inflictor == NULL || !(inflictor->flags5 & MF5_PAINLESS)) && (target->player != NULL || !G_SkillProperty(SKILLP_NoPain)) && !(target->flags & MF_SKULLFLY)) @@ -1474,6 +1522,14 @@ dopain: if (justhit && (target->target == source || !target->target || !target->IsFriend(target->target))) target->flags |= MF_JUSTHIT; // fight back! + if (invulpain) //Note that this takes into account all the cheats a player has, in terms of invulnerability. + { + return -1; //NOW we return -1! + } + else if (target->flags7 & MF7_ALLOWPAIN) + { + return holdDamage; + } return damage; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a92eed8f8..bae4563b3 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -5986,7 +5986,7 @@ bool AActor::IsHostile (AActor *other) int AActor::DoSpecialDamage (AActor *target, int damage, FName damagetype) { if (target->player && target->player->mo == target && damage < 1000 && - (target->player->cheats & CF_GODMODE)) + (target->player->cheats & CF_GODMODE || target->player->cheats & CF_GODMODE2)) { return -1; } diff --git a/src/p_user.cpp b/src/p_user.cpp index 045e61969..8eddf3135 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2588,7 +2588,8 @@ void P_PlayerThink (player_t *player) { if (player->mo->waterlevel < 3 || (player->mo->flags2 & MF2_INVULNERABLE) || - (player->cheats & (CF_GODMODE | CF_NOCLIP2))) + (player->cheats & (CF_GODMODE | CF_NOCLIP2)) || + (player->cheats & CF_GODMODE2)) { player->mo->ResetAirSupply (); } diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index dbd1f1031..347b2e01a 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -245,6 +245,7 @@ static FFlagDef ActorFlags[]= DEFINE_FLAG(MF7, BUDDHA, AActor, flags7), DEFINE_FLAG(MF7, FOILBUDDHA, AActor, flags7), DEFINE_FLAG(MF7, DONTTHRUST, AActor, flags7), + DEFINE_FLAG(MF7, ALLOWPAIN, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),