mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-18 23:21:41 +00:00
Merge branch 'master' of https://github.com/rheit/zdoom into z_osx_clean
This commit is contained in:
commit
1074a031a2
30 changed files with 430 additions and 153 deletions
|
@ -344,6 +344,8 @@ 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_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 ---
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
14
src/b_bot.h
14
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);
|
||||
|
|
159
src/b_game.cpp
159
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;
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ typedef enum
|
|||
ga_loadlevel,
|
||||
ga_newgame,
|
||||
ga_newgame2,
|
||||
ga_recordgame,
|
||||
ga_loadgame,
|
||||
ga_loadgamehidecon,
|
||||
ga_loadgameplaydemo,
|
||||
|
|
|
@ -1338,6 +1338,7 @@ CCMD (endgame)
|
|||
{
|
||||
gameaction = ga_fullconsole;
|
||||
demosequence = -1;
|
||||
G_CheckDemoStatus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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_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_DONTTHRUST))
|
||||
{
|
||||
randVal = pr_foo();
|
||||
if (randVal > 160)
|
||||
|
|
|
@ -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)
|
||||
|
@ -236,6 +276,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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -1053,17 +1078,20 @@ 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);
|
||||
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,22 +1109,29 @@ 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)
|
||||
&& !(target->flags7 & MF7_DONTTHRUST)
|
||||
&& (source == NULL || source->player == NULL || !(source->flags2 & MF2_NODMGTHRUST)))
|
||||
{
|
||||
int kickback;
|
||||
|
@ -1133,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)
|
||||
|
@ -1146,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;
|
||||
|
@ -1214,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;
|
||||
}
|
||||
|
||||
|
@ -1231,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;
|
||||
}
|
||||
|
@ -1295,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1324,7 +1367,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
|
||||
|
@ -1382,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))
|
||||
|
@ -1473,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;
|
||||
}
|
||||
|
||||
|
@ -1591,7 +1648,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;
|
||||
}
|
||||
|
@ -1642,8 +1699,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;
|
||||
}
|
||||
|
|
|
@ -560,6 +560,7 @@ enum EDmgFlags
|
|||
DMG_PLAYERATTACK = 32,
|
||||
DMG_FOILINVUL = 64,
|
||||
DMG_FOILBUDDHA = 128,
|
||||
DMG_NO_PROTECT = 256,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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_DONTTHRUST)))
|
||||
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_DONTTHRUST))
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -696,6 +696,7 @@ public:
|
|||
|
||||
case NAME_FillColor:
|
||||
th->fillcolor = CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Health:
|
||||
th->health = CheckInt(key);
|
||||
|
@ -1540,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)
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -4004,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)
|
||||
|
@ -4053,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!
|
||||
|
||||
|
@ -4459,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;
|
||||
|
@ -4608,17 +4672,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 +4765,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RadiusGive)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if (thing->flags & MF_MISSILE)
|
||||
{
|
||||
if (!(flags & RGF_MISSILES))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
|
@ -4724,8 +4797,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 ((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)))
|
||||
{
|
||||
|
@ -4832,6 +4905,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 +4921,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.
|
||||
|
|
|
@ -244,6 +244,8 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_FLAG(MF7, HARMFRIENDS, AActor, flags7),
|
||||
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),
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -191,15 +193,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
|
||||
|
@ -383,6 +387,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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue